diff --git a/product-mixer/README.md b/product-mixer/README.md
deleted file mode 100644
index 1852d96c0..000000000
--- a/product-mixer/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-Product Mixer
-=============
-
-## Overview
-
-Product Mixer is a common service framework and set of libraries that make it easy to build,
-iterate on, and own product surface areas. It consists of:
-
-- **Core Libraries:** A set of libraries that enable you to build execution pipelines out of
- reusable components. You define your logic in small, well-defined, reusable components and focus
- on expressing the business logic you want to have. Then you can define easy to understand pipelines
- that compose your components. Product Mixer handles the execution and monitoring of your pipelines
- allowing you to focus on what really matters, your business logic.
-
-- **Service Framework:** A common service skeleton for teams to host their Product Mixer products.
-
-- **Component Library:** A shared library of components made by the Product Mixer Team, or
- contributed by users. This enables you to both easily share the reusable components you make as well
- as benefit from the work other teams have done by utilizing their shared components in the library.
-
-## Architecture
-
-The bulk of a Product Mixer can be broken down into Pipelines and Components. Components allow you
-to break business logic into separate, standardized, reusable, testable, and easily composable
-pieces, where each component has a well defined abstraction. Pipelines are essentially configuration
-files specifying which Components should be used and when. This makes it easy to understand how your
-code will execute while keeping it organized and structured in a maintainable way.
-
-Requests first go to Product Pipelines, which are used to select which Mixer Pipeline or
-Recommendation Pipeline to run for a given request. Each Mixer or Recommendation
-Pipeline may run multiple Candidate Pipelines to fetch candidates to include in the response.
-
-Mixer Pipelines combine the results of multiple heterogeneous Candidate Pipelines together
-(e.g. ads, tweets, users) while Recommendation Pipelines are used to score (via Scoring Pipelines)
-and rank the results of homogenous Candidate Pipelines so that the top ranked ones can be returned.
-These pipelines also marshall candidates into a domain object and then into a transport object
-to return to the caller.
-
-Candidate Pipelines fetch candidates from underlying Candidate Sources and perform some basic
-operations on the Candidates, such as filtering out unwanted candidates, applying decorations,
-and hydrating features.
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala
deleted file mode 100644
index 72698e1c7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer
-
-import com.twitter.account_recommendations_mixer.{thriftscala => t}
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object WhoToFollowModuleHeaderFeature extends Feature[UserCandidate, t.Header]
-object WhoToFollowModuleFooterFeature extends Feature[UserCandidate, Option[t.Footer]]
-object WhoToFollowModuleDisplayOptionsFeature
- extends Feature[UserCandidate, Option[t.DisplayOptions]]
-
-@Singleton
-class AccountRecommendationsMixerCandidateSource @Inject() (
- accountRecommendationsMixer: t.AccountRecommendationsMixer.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[
- t.AccountRecommendationsMixerRequest,
- t.RecommendedUser
- ] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier(name = "AccountRecommendationsMixer")
-
- override def apply(
- request: t.AccountRecommendationsMixerRequest
- ): Stitch[CandidatesWithSourceFeatures[t.RecommendedUser]] = {
- Stitch
- .callFuture(accountRecommendationsMixer.getWtfRecommendations(request))
- .map { response: t.WhoToFollowResponse =>
- responseToCandidatesWithSourceFeatures(
- response.userRecommendations,
- response.header,
- response.footer,
- response.displayOptions)
- }
- }
-
- private def responseToCandidatesWithSourceFeatures(
- userRecommendations: Seq[t.RecommendedUser],
- header: t.Header,
- footer: Option[t.Footer],
- displayOptions: Option[t.DisplayOptions],
- ): CandidatesWithSourceFeatures[t.RecommendedUser] = {
- val features = FeatureMapBuilder()
- .add(WhoToFollowModuleHeaderFeature, header)
- .add(WhoToFollowModuleFooterFeature, footer)
- .add(WhoToFollowModuleDisplayOptionsFeature, displayOptions)
- .build()
- CandidatesWithSourceFeatures(userRecommendations, features)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD
deleted file mode 100644
index d5eaef320..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "stitch/stitch-core",
- ],
- exports = [
- "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala
deleted file mode 100644
index 0509738a0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.adserver.thriftscala.AdRequestParams
-import com.twitter.adserver.thriftscala.AdRequestResponse
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.ads.admixer.MakeAdRequestClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsProdStratoCandidateSource @Inject() (adsClient: MakeAdRequestClientColumn)
- extends StratoKeyFetcherSource[
- AdRequestParams,
- AdRequestResponse,
- AdImpression
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("AdsProdStrato")
-
- override val fetcher: Fetcher[AdRequestParams, Unit, AdRequestResponse] = adsClient.fetcher
-
- override protected def stratoResultTransformer(
- stratoResult: AdRequestResponse
- ): Seq[AdImpression] =
- stratoResult.impressions
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala
deleted file mode 100644
index 08df2eb0d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.adserver.thriftscala.AdRequestParams
-import com.twitter.adserver.thriftscala.NewAdServer
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsProdThriftCandidateSource @Inject() (
- adServerClient: NewAdServer.MethodPerEndpoint)
- extends CandidateSource[AdRequestParams, AdImpression] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("AdsProdThrift")
-
- override def apply(request: AdRequestParams): Stitch[Seq[AdImpression]] =
- Stitch.callFuture(adServerClient.makeAdRequest(request)).map(_.impressions)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala
deleted file mode 100644
index d719f7608..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.adserver.thriftscala.AdRequestParams
-import com.twitter.adserver.thriftscala.AdRequestResponse
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.ads.admixer.MakeAdRequestStagingClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsStagingCandidateSource @Inject() (adsClient: MakeAdRequestStagingClientColumn)
- extends StratoKeyFetcherSource[
- AdRequestParams,
- AdRequestResponse,
- AdImpression
- ] {
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("AdsStaging")
-
- override val fetcher: Fetcher[AdRequestParams, Unit, AdRequestResponse] = adsClient.fetcher
-
- override protected def stratoResultTransformer(
- stratoResult: AdRequestResponse
- ): Seq[AdImpression] =
- stratoResult.impressions
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD
deleted file mode 100644
index f3b49ec31..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala",
- "strato/config/columns/ads/admixer:admixer-strato-client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala
deleted file mode 100644
index 53bbb8d4f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.ann
-
-import com.twitter.ann.common._
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import com.twitter.util.{Time => _, _}
-import com.twitter.finagle.util.DefaultTimer
-
-/**
- * @param annQueryableById Ann Queryable by Id client that returns nearest neighbors for a sequence of queries
- * @param identifier Candidate Source Identifier
- * @tparam T1 type of the query.
- * @tparam T2 type of the result.
- * @tparam P runtime parameters supported by the index.
- * @tparam D distance function used in the index.
- */
-class AnnCandidateSource[T1, T2, P <: RuntimeParams, D <: Distance[D]](
- val annQueryableById: QueryableById[T1, T2, P, D],
- val batchSize: Int,
- val timeoutPerRequest: Duration,
- override val identifier: CandidateSourceIdentifier)
- extends CandidateSource[AnnIdQuery[T1, P], NeighborWithDistanceWithSeed[T1, T2, D]] {
-
- implicit val timer = DefaultTimer
-
- override def apply(
- request: AnnIdQuery[T1, P]
- ): Stitch[Seq[NeighborWithDistanceWithSeed[T1, T2, D]]] = {
- val ids = request.ids
- val numOfNeighbors = request.numOfNeighbors
- val runtimeParams = request.runtimeParams
- Stitch
- .collect(
- ids
- .grouped(batchSize).map { batchedIds =>
- annQueryableById
- .batchQueryWithDistanceById(batchedIds, numOfNeighbors, runtimeParams).map {
- annResult => annResult.toSeq
- }.within(timeoutPerRequest).handle { case _ => Seq.empty }
- }.toSeq).map(_.flatten)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala
deleted file mode 100644
index b262f6ac4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.ann
-
-import com.twitter.ann.common._
-
-/**
- * A [[AnnIdQuery]] is a query class which defines the ann entities with runtime params and number of neighbors requested
- *
- * @param ids Sequence of queries
- * @param numOfNeighbors Number of neighbors requested
- * @param runtimeParams ANN Runtime Params
- * @param batchSize Batch size to the stitch client
- * @tparam T type of query.
- * @tparam P runtime parameters supported by the index.
- */
-case class AnnIdQuery[T, P <: RuntimeParams](
- ids: Seq[T],
- numOfNeighbors: Int,
- runtimeParams: P)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel
deleted file mode 100644
index 46b1efdbb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "ann/src/main/scala/com/twitter/ann/common",
- "ann/src/main/scala/com/twitter/ann/hnsw",
- "ann/src/main/thrift/com/twitter/ann/common:ann-common-scala",
- "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "servo/manhattan/src/main/scala",
- "servo/repo/src/main/scala",
- "servo/util/src/main/scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel
deleted file mode 100644
index 8b93dea9f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/periscope/audio_space:audio_space-scala",
- "strato/config/columns/periscope:periscope-strato-client",
- "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala
deleted file mode 100644
index c5b820065..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.audiospace
-
-import com.twitter.periscope.audio_space.thriftscala.CreatedSpacesView
-import com.twitter.periscope.audio_space.thriftscala.SpaceSlice
-import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature
-import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherWithSourceFeaturesSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.periscope.CreatedSpacesSliceOnUserClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CreatedSpacesCandidateSource @Inject() (
- column: CreatedSpacesSliceOnUserClientColumn)
- extends StratoKeyViewFetcherWithSourceFeaturesSource[
- Long,
- CreatedSpacesView,
- SpaceSlice,
- String
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("CreatedSpaces")
-
- override val fetcher: Fetcher[Long, CreatedSpacesView, SpaceSlice] = column.fetcher
-
- override def stratoResultTransformer(
- stratoKey: Long,
- stratoResult: SpaceSlice
- ): Seq[String] =
- stratoResult.items
-
- override protected def extractFeaturesFromStratoResult(
- stratoKey: Long,
- stratoResult: SpaceSlice
- ): FeatureMap = {
- val featureMapBuilder = FeatureMapBuilder()
- stratoResult.sliceInfo.previousCursor.foreach { cursor =>
- featureMapBuilder.add(PreviousCursorFeature, cursor)
- }
- stratoResult.sliceInfo.nextCursor.foreach { cursor =>
- featureMapBuilder.add(NextCursorFeature, cursor)
- }
- featureMapBuilder.build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD
deleted file mode 100644
index 0f5552bb5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "strato/config/columns/consumer-identity/business-profiles:business-profiles-strato-client",
- "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala
deleted file mode 100644
index c728194ab..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.business_profiles
-
-import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature
-import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherWithSourceFeaturesSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn
-import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn.{
- Value => TeamMembersSlice
-}
-import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn.{
- View => TeamMembersView
-}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TeamMembersCandidateSource @Inject() (
- column: BusinessProfileTeamMembersOnUserClientColumn)
- extends StratoKeyViewFetcherWithSourceFeaturesSource[
- Long,
- TeamMembersView,
- TeamMembersSlice,
- Long
- ] {
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier(
- "BusinessProfileTeamMembers")
-
- override val fetcher: Fetcher[Long, TeamMembersView, TeamMembersSlice] = column.fetcher
-
- override def stratoResultTransformer(
- stratoKey: Long,
- stratoResult: TeamMembersSlice
- ): Seq[Long] =
- stratoResult.members
-
- override protected def extractFeaturesFromStratoResult(
- stratoKey: Long,
- stratoResult: TeamMembersSlice
- ): FeatureMap = {
- val featureMapBuilder = FeatureMapBuilder()
- stratoResult.previousCursor.foreach { cursor =>
- featureMapBuilder.add(PreviousCursorFeature, cursor.toString)
- }
- stratoResult.nextCursor.foreach { cursor =>
- featureMapBuilder.add(NextCursorFeature, cursor.toString)
- }
- featureMapBuilder.build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel
deleted file mode 100644
index 1eef70e77..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel
+++ /dev/null
@@ -1,12 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "cr-mixer/thrift/src/main/thrift:thrift-scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala
deleted file mode 100644
index c1e79f238..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.cr_mixer
-
-import com.twitter.cr_mixer.{thriftscala => t}
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Returns out-of-network Tweet recommendations by using user recommendations
- * from FollowRecommendationService as an input seed-set to Earlybird
- */
-@Singleton
-class CrMixerFrsBasedTweetRecommendationsCandidateSource @Inject() (
- crMixerClient: t.CrMixer.MethodPerEndpoint)
- extends CandidateSource[t.FrsTweetRequest, t.FrsTweet] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("CrMixerFrsBasedTweetRecommendations")
-
- override def apply(request: t.FrsTweetRequest): Stitch[Seq[t.FrsTweet]] = Stitch
- .callFuture(crMixerClient.getFrsBasedTweetRecommendations(request))
- .map(_.tweets)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala
deleted file mode 100644
index a0cbd666c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.cr_mixer
-
-import com.twitter.cr_mixer.{thriftscala => t}
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CrMixerTweetRecommendationsCandidateSource @Inject() (
- crMixerClient: t.CrMixer.MethodPerEndpoint)
- extends CandidateSource[t.CrMixerTweetRequest, t.TweetRecommendation] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("CrMixerTweetRecommendations")
-
- override def apply(request: t.CrMixerTweetRequest): Stitch[Seq[t.TweetRecommendation]] = Stitch
- .callFuture(crMixerClient.getTweetRecommendations(request))
- .map(_.tweets)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel
deleted file mode 100644
index 638f549d3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel
+++ /dev/null
@@ -1,12 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "src/thrift/com/twitter/search:earlybird-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala
deleted file mode 100644
index 9049849be..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.earlybird
-
-import com.twitter.search.earlybird.{thriftscala => t}
-import com.twitter.inject.Logging
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class EarlybirdTweetCandidateSource @Inject() (
- earlybirdService: t.EarlybirdService.MethodPerEndpoint)
- extends CandidateSource[t.EarlybirdRequest, t.ThriftSearchResult]
- with Logging {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("EarlybirdTweets")
-
- override def apply(request: t.EarlybirdRequest): Stitch[Seq[t.ThriftSearchResult]] = {
- Stitch
- .callFuture(earlybirdService.search(request))
- .map { response: t.EarlybirdResponse =>
- response.searchResults.map(_.results).getOrElse(Seq.empty)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel
deleted file mode 100644
index 6633be199..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel
+++ /dev/null
@@ -1,12 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "explore/explore-ranker/thrift/src/main/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala
deleted file mode 100644
index bd57b785a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.explore_ranker
-
-import com.twitter.explore_ranker.{thriftscala => t}
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ExploreRankerCandidateSource @Inject() (
- exploreRankerService: t.ExploreRanker.MethodPerEndpoint)
- extends CandidateSource[t.ExploreRankerRequest, t.ImmersiveRecsResult] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("ExploreRanker")
-
- override def apply(
- request: t.ExploreRankerRequest
- ): Stitch[Seq[t.ImmersiveRecsResult]] = {
- Stitch
- .callFuture(exploreRankerService.getRankedResults(request))
- .map {
- case t.ExploreRankerResponse(
- t.ExploreRankerProductResponse
- .ImmersiveRecsResponse(t.ImmersiveRecsResponse(immersiveRecsResults))) =>
- immersiveRecsResults
- case response =>
- throw new UnsupportedOperationException(s"Unknown response type: $response")
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD
deleted file mode 100644
index b456956db..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
- exports = [
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala
deleted file mode 100644
index 48891d7ec..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline
-
-import com.twitter.inject.Logging
-import com.twitter.onboarding.injections.{thriftscala => injectionsthrift}
-import com.twitter.onboarding.task.service.{thriftscala => servicethrift}
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Returns a list of prompts to insert into a user's timeline (inline prompt, cover modals, etc)
- * from go/flip (the prompting platform for Twitter).
- */
-@Singleton
-class PromptCandidateSource @Inject() (taskService: servicethrift.TaskService.MethodPerEndpoint)
- extends CandidateSource[servicethrift.GetInjectionsRequest, IntermediatePrompt]
- with Logging {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier(
- "InjectionPipelinePrompts")
-
- override def apply(
- request: servicethrift.GetInjectionsRequest
- ): Stitch[Seq[IntermediatePrompt]] = {
- Stitch
- .callFuture(taskService.getInjections(request)).map {
- _.injections.flatMap {
- // The entire carousel is getting added to each IntermediatePrompt item with a
- // corresponding index to be unpacked later on to populate its TimelineEntry counterpart.
- case injection: injectionsthrift.Injection.TilesCarousel =>
- injection.tilesCarousel.tiles.zipWithIndex.map {
- case (tile: injectionsthrift.Tile, index: Int) =>
- IntermediatePrompt(injection, Some(index), Some(tile))
- }
- case injection => Seq(IntermediatePrompt(injection, None, None))
- }
- }
- }
-}
-
-/**
- * Gives an intermediate step to help 'explosion' of tile carousel tiles due to TimelineModule
- * not being an extension of TimelineItem
- */
-case class IntermediatePrompt(
- injection: injectionsthrift.Injection,
- offsetInModule: Option[Int],
- carouselTile: Option[injectionsthrift.Tile])
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel
deleted file mode 100644
index c6bcf152a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/hermit:hermit-scala",
- "strato/config/columns/onboarding:onboarding-strato-client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/hermit:hermit-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala
deleted file mode 100644
index 9bbfe234a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.hermit
-
-import com.twitter.hermit.thriftscala.RecommendationRequest
-import com.twitter.hermit.thriftscala.RecommendationResponse
-import com.twitter.hermit.thriftscala.RelatedUser
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.onboarding.HermitRecommendUsersClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UsersSimilarToMeCandidateSource @Inject() (
- column: HermitRecommendUsersClientColumn)
- extends StratoKeyViewFetcherSource[
- Long,
- RecommendationRequest,
- RecommendationResponse,
- RelatedUser
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("UsersSimilarToMe")
-
- override val fetcher: Fetcher[Long, RecommendationRequest, RecommendationResponse] =
- column.fetcher
-
- override def stratoResultTransformer(
- stratoKey: Long,
- result: RecommendationResponse
- ): Seq[RelatedUser] = result.suggestions.getOrElse(Seq.empty).filter(_.id.isDefined)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD
deleted file mode 100644
index da4c6d794..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "interests-service/thrift/src/main/thrift:thrift-scala",
- "interests_discovery/thrift/src/main/thrift:service-thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
- exports = [
- "interests-service/thrift/src/main/thrift:thrift-scala",
- "interests_discovery/thrift/src/main/thrift:service-thrift-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala
deleted file mode 100644
index 30465089c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.interest_discovery
-
-import com.google.inject.Inject
-import com.google.inject.Singleton
-import com.twitter.inject.Logging
-import com.twitter.interests_discovery.{thriftscala => t}
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-
-/**
- * Generate a list of related topics results from IDS getRelatedTopics (thrift) endpoint.
- * Returns related topics, given a topic, whereas [[RecommendedTopicsCandidateSource]] returns
- * recommended topics, given a user.
- */
-@Singleton
-class RelatedTopicsCandidateSource @Inject() (
- interestDiscoveryService: t.InterestsDiscoveryService.MethodPerEndpoint)
- extends CandidateSource[t.RelatedTopicsRequest, t.RelatedTopic]
- with Logging {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier(name = "RelatedTopics")
-
- override def apply(
- request: t.RelatedTopicsRequest
- ): Stitch[Seq[t.RelatedTopic]] = {
- Stitch
- .callFuture(interestDiscoveryService.getRelatedTopics(request))
- .map { response: t.RelatedTopicsResponse =>
- response.topics
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel
deleted file mode 100644
index c62b67377..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "interests_discovery/thrift/src/main/thrift:service-thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "strato/config/columns/recommendations/interests_discovery/recommendations_mh:recommendations_mh-strato-client",
- ],
- exports = [
- "strato/config/columns/recommendations/interests_discovery/recommendations_mh:recommendations_mh-strato-client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala
deleted file mode 100644
index a8b6f214c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.lists
-
-import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.recommendations.interests_discovery.recommendations_mh.OrganicPopgeoListsClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class OrganicPopGeoListsCandidateSource @Inject() (
- organicPopgeoListsClientColumn: OrganicPopgeoListsClientColumn)
- extends StratoKeyFetcherSource[
- OrganicPopgeoListsClientColumn.Key,
- OrganicPopgeoListsClientColumn.Value,
- TwitterListCandidate
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier(
- "OrganicPopGeoLists")
-
- override val fetcher: Fetcher[
- OrganicPopgeoListsClientColumn.Key,
- Unit,
- OrganicPopgeoListsClientColumn.Value
- ] =
- organicPopgeoListsClientColumn.fetcher
-
- override def stratoResultTransformer(
- stratoResult: OrganicPopgeoListsClientColumn.Value
- ): Seq[TwitterListCandidate] = {
- stratoResult.recommendedListsByAlgo.flatMap { topLists =>
- topLists.lists.map { list =>
- TwitterListCandidate(list.listId)
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD
deleted file mode 100644
index a54812ce9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "people-discovery/api/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "src/thrift/com/twitter/hermit:hermit-scala",
- "stitch/stitch-core",
- ],
- exports = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "people-discovery/api/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala
deleted file mode 100644
index 0b3dacccb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.people_discovery
-
-import com.twitter.peoplediscovery.api.{thriftscala => t}
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult
-import com.twitter.stitch.Stitch
-import com.twitter.util.logging.Logging
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object WhoToFollowModuleHeaderFeature extends Feature[UserCandidate, t.Header]
-object WhoToFollowModuleDisplayOptionsFeature
- extends Feature[UserCandidate, Option[t.DisplayOptions]]
-object WhoToFollowModuleShowMoreFeature extends Feature[UserCandidate, Option[t.ShowMore]]
-
-@Singleton
-class PeopleDiscoveryCandidateSource @Inject() (
- peopleDiscoveryService: t.ThriftPeopleDiscoveryService.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[t.GetModuleRequest, t.RecommendedUser]
- with Logging {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier(name = "PeopleDiscovery")
-
- override def apply(
- request: t.GetModuleRequest
- ): Stitch[CandidatesWithSourceFeatures[t.RecommendedUser]] = {
- Stitch
- .callFuture(peopleDiscoveryService.getModules(request))
- .map { response: t.GetModuleResponse =>
- // under the assumption getModules returns a maximum of one module
- response.modules
- .collectFirst { module =>
- module.layout match {
- case t.Layout.UserBioList(layout) =>
- layoutToCandidatesWithSourceFeatures(
- layout.userRecommendations,
- layout.header,
- layout.displayOptions,
- layout.showMore)
- case t.Layout.UserTweetCarousel(layout) =>
- layoutToCandidatesWithSourceFeatures(
- layout.userRecommendations,
- layout.header,
- layout.displayOptions,
- layout.showMore)
- }
- }.getOrElse(throw PipelineFailure(UnexpectedCandidateResult, "unexpected missing module"))
- }
- }
-
- private def layoutToCandidatesWithSourceFeatures(
- userRecommendations: Seq[t.RecommendedUser],
- header: t.Header,
- displayOptions: Option[t.DisplayOptions],
- showMore: Option[t.ShowMore],
- ): CandidatesWithSourceFeatures[t.RecommendedUser] = {
- val features = FeatureMapBuilder()
- .add(WhoToFollowModuleHeaderFeature, header)
- .add(WhoToFollowModuleDisplayOptionsFeature, displayOptions)
- .add(WhoToFollowModuleShowMoreFeature, showMore)
- .build()
- CandidatesWithSourceFeatures(userRecommendations, features)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel
deleted file mode 100644
index cb69d82ec..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "follow-recommendations-service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "strato/config/columns/onboarding/follow-recommendations-service:follow-recommendations-service-strato-client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala
deleted file mode 100644
index dcfed2ec9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.recommendations
-
-import com.twitter.follow_recommendations.{thriftscala => fr}
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.onboarding.follow_recommendations_service.GetRecommendationsClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Returns a list of FollowRecommendations as [[fr.UserRecommendation]]s fetched from Strato
- */
-@Singleton
-class UserFollowRecommendationsCandidateSource @Inject() (
- getRecommendationsClientColumn: GetRecommendationsClientColumn)
- extends StratoKeyViewFetcherSource[
- fr.RecommendationRequest,
- Unit,
- fr.RecommendationResponse,
- fr.UserRecommendation
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier(
- "FollowRecommendationsService")
-
- override val fetcher: Fetcher[fr.RecommendationRequest, Unit, fr.RecommendationResponse] =
- getRecommendationsClientColumn.fetcher
-
- override def stratoResultTransformer(
- stratoKey: fr.RecommendationRequest,
- stratoResult: fr.RecommendationResponse
- ): Seq[fr.UserRecommendation] = {
- stratoResult.recommendations.map {
- case fr.Recommendation.User(userRec: fr.UserRecommendation) =>
- userRec
- case _ =>
- throw new Exception("Invalid recommendation type returned from FRS")
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel
deleted file mode 100644
index dbc8cba53..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "socialgraph/server/src/main/scala/com/twitter/socialgraph/util",
- "src/thrift/com/twitter/socialgraph:thrift-scala",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/socialgraph:thrift-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala
deleted file mode 100644
index b3cf838f2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.social_graph
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorType
-import com.twitter.product_mixer.component_library.model.candidate.NextCursor
-import com.twitter.product_mixer.component_library.model.candidate.PreviousCursor
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.socialgraph.thriftscala
-import com.twitter.socialgraph.thriftscala.IdsRequest
-import com.twitter.socialgraph.thriftscala.IdsResult
-import com.twitter.socialgraph.util.ByteBufferUtil
-import com.twitter.strato.client.Fetcher
-import javax.inject.Inject
-import javax.inject.Singleton
-
-sealed trait SocialgraphResponse
-case class SocialgraphResult(id: Long) extends SocialgraphResponse
-case class SocialgraphCursor(cursor: Long, cursorType: CursorType) extends SocialgraphResponse
-
-@Singleton
-class SocialgraphCandidateSource @Inject() (
- override val fetcher: Fetcher[thriftscala.IdsRequest, Option[
- thriftscala.RequestContext
- ], thriftscala.IdsResult])
- extends StratoKeyViewFetcherSource[
- thriftscala.IdsRequest,
- Option[thriftscala.RequestContext],
- thriftscala.IdsResult,
- SocialgraphResponse
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("Socialgraph")
-
- override def stratoResultTransformer(
- stratoKey: IdsRequest,
- stratoResult: IdsResult
- ): Seq[SocialgraphResponse] = {
- val prevCursor =
- SocialgraphCursor(ByteBufferUtil.toLong(stratoResult.pageResult.prevCursor), PreviousCursor)
- /* When an end cursor is passed to Socialgraph,
- * Socialgraph returns the start cursor. To prevent
- * clients from circularly fetching the timeline again,
- * if we see a start cursor returned from Socialgraph,
- * we replace it with an end cursor.
- */
- val nextCursor = ByteBufferUtil.toLong(stratoResult.pageResult.nextCursor) match {
- case SocialgraphCursorConstants.StartCursor =>
- SocialgraphCursor(SocialgraphCursorConstants.EndCursor, NextCursor)
- case cursor => SocialgraphCursor(cursor, NextCursor)
- }
-
- stratoResult.ids
- .map { id =>
- SocialgraphResult(id)
- } ++ Seq(nextCursor, prevCursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala
deleted file mode 100644
index 8f187d0cb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.social_graph
-
-object SocialgraphCursorConstants {
- val EndCursor: Long = 0L
- val StartCursor: Long = -1L
- val LastSortIndex: Long = 0L
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel
deleted file mode 100644
index c83297fd8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "src/thrift/com/twitter/timelineranker:thrift-scala",
- "src/thrift/com/twitter/timelineranker/server/model:thrift-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala
deleted file mode 100644
index 9f1262e53..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelineranker.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Map of tweetId -> sourceTweet of retweets present in Timeline Ranker candidates list.
- * These tweets are used only for further ranking. They are not returned to the end user.
- */
-object TimelineRankerInNetworkSourceTweetsByTweetIdMapFeature
- extends Feature[PipelineQuery, Map[Long, t.CandidateTweet]]
-
-@Singleton
-class TimelineRankerInNetworkCandidateSource @Inject() (
- timelineRankerClient: t.TimelineRanker.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[t.RecapQuery, t.CandidateTweet] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("TimelineRankerInNetwork")
-
- override def apply(
- request: t.RecapQuery
- ): Stitch[CandidatesWithSourceFeatures[t.CandidateTweet]] = {
- Stitch
- .callFuture(timelineRankerClient.getRecycledTweetCandidates(Seq(request)))
- .map { response: Seq[t.GetCandidateTweetsResponse] =>
- val candidates =
- response.headOption.flatMap(_.candidates).getOrElse(Seq.empty).filter(_.tweet.nonEmpty)
- val sourceTweetsByTweetId =
- response.headOption
- .flatMap(_.sourceTweets).getOrElse(Seq.empty).filter(_.tweet.nonEmpty)
- .map { candidate =>
- (candidate.tweet.get.id, candidate)
- }.toMap
- val sourceTweetsByTweetIdMapFeature = FeatureMapBuilder()
- .add(TimelineRankerInNetworkSourceTweetsByTweetIdMapFeature, sourceTweetsByTweetId)
- .build()
- CandidatesWithSourceFeatures(
- candidates = candidates,
- features = sourceTweetsByTweetIdMapFeature)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala
deleted file mode 100644
index 7cd36fb92..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import com.twitter.timelineranker.{thriftscala => t}
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineRankerRecapCandidateSource @Inject() (
- timelineRankerClient: t.TimelineRanker.MethodPerEndpoint)
- extends CandidateSource[t.RecapQuery, t.CandidateTweet] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("TimelineRankerRecap")
-
- override def apply(
- request: t.RecapQuery
- ): Stitch[Seq[t.CandidateTweet]] = {
- Stitch
- .callFuture(timelineRankerClient.getRecapCandidatesFromAuthors(Seq(request)))
- .map { response: Seq[t.GetCandidateTweetsResponse] =>
- response.headOption.flatMap(_.candidates).getOrElse(Seq.empty).filter(_.tweet.nonEmpty)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala
deleted file mode 100644
index bee6fe128..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult
-import com.twitter.stitch.Stitch
-import com.twitter.timelineranker.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Source tweets of retweets present in Timeline Ranker candidates list.
- * These tweets are used only for further ranking. They are not returned to the end user.
- */
-case object TimelineRankerUtegSourceTweetsFeature
- extends Feature[PipelineQuery, Seq[t.CandidateTweet]]
-
-@Singleton
-class TimelineRankerUtegCandidateSource @Inject() (
- timelineRankerClient: t.TimelineRanker.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[t.UtegLikedByTweetsQuery, t.CandidateTweet] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("TimelineRankerUteg")
-
- override def apply(
- request: t.UtegLikedByTweetsQuery
- ): Stitch[CandidatesWithSourceFeatures[t.CandidateTweet]] = {
- Stitch
- .callFuture(timelineRankerClient.getUtegLikedByTweetCandidates(Seq(request)))
- .map { response =>
- val result = response.headOption.getOrElse(
- throw PipelineFailure(UnexpectedCandidateResult, "Empty Timeline Ranker response"))
- val candidates = result.candidates.toSeq.flatten
- val sourceTweets = result.sourceTweets.toSeq.flatten
-
- val candidateSourceFeatures = FeatureMapBuilder()
- .add(TimelineRankerUtegSourceTweetsFeature, sourceTweets)
- .build()
-
- CandidatesWithSourceFeatures(candidates = candidates, features = candidateSourceFeatures)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel
deleted file mode 100644
index e4435bc0a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "src/thrift/com/twitter/timelineservice/server/suggests/features:thrift-scala",
- "src/thrift/com/twitter/timelineservice/server/suggests/logging:thrift-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala
deleted file mode 100644
index b2d6f3912..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala
+++ /dev/null
@@ -1,156 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timeline_scorer
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelinescorer.common.scoredtweetcandidate.thriftscala.v1
-import com.twitter.timelinescorer.common.scoredtweetcandidate.thriftscala.v1.Ancestor
-import com.twitter.timelinescorer.common.scoredtweetcandidate.{thriftscala => ct}
-import com.twitter.timelinescorer.{thriftscala => t}
-import com.twitter.timelineservice.suggests.logging.candidate_tweet_source_id.thriftscala.CandidateTweetSourceId
-import javax.inject.Inject
-import javax.inject.Singleton
-
-case class ScoredTweetCandidateWithFocalTweet(
- candidate: v1.ScoredTweetCandidate,
- focalTweetIdOpt: Option[Long])
-
-case object TimelineScorerCandidateSourceSucceededFeature extends Feature[PipelineQuery, Boolean]
-
-@Singleton
-class TimelineScorerCandidateSource @Inject() (
- timelineScorerClient: t.TimelineScorer.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[
- t.ScoredTweetsRequest,
- ScoredTweetCandidateWithFocalTweet
- ] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("TimelineScorer")
-
- private val MaxConversationAncestors = 2
-
- override def apply(
- request: t.ScoredTweetsRequest
- ): Stitch[CandidatesWithSourceFeatures[ScoredTweetCandidateWithFocalTweet]] = {
- Stitch
- .callFuture(timelineScorerClient.getScoredTweets(request))
- .map { response =>
- val scoredTweetsOpt = response match {
- case t.ScoredTweetsResponse.V1(v1) => v1.scoredTweets
- case t.ScoredTweetsResponse.UnknownUnionField(field) =>
- throw new UnsupportedOperationException(s"Unknown response type: ${field.field.name}")
- }
- val scoredTweets = scoredTweetsOpt.getOrElse(Seq.empty)
-
- val allAncestors = scoredTweets.flatMap {
- case ct.ScoredTweetCandidate.V1(v1) if isEligibleReply(v1) =>
- v1.ancestors.get.map(_.tweetId)
- case _ => Seq.empty
- }.toSet
-
- // Remove tweets within ancestor list of other tweets to avoid serving duplicates
- val keptTweets = scoredTweets.collect {
- case ct.ScoredTweetCandidate.V1(v1) if !allAncestors.contains(originalTweetId(v1)) => v1
- }
-
- // Add parent and root tweet for eligible reply focal tweets
- val candidates = keptTweets
- .flatMap {
- case v1 if isEligibleReply(v1) =>
- val ancestors = v1.ancestors.get
- val focalTweetId = v1.tweetId
-
- // Include root tweet if the conversation has atleast 2 ancestors
- val optionallyIncludedRootTweet = if (ancestors.size >= MaxConversationAncestors) {
- val rootTweet = toScoredTweetCandidateFromAncestor(
- ancestor = ancestors.last,
- inReplyToTweetId = None,
- conversationId = v1.conversationId,
- ancestors = None,
- candidateTweetSourceId = v1.candidateTweetSourceId
- )
- Seq((rootTweet, Some(v1)))
- } else Seq.empty
-
- /**
- * Setting the in-reply-to tweet id on the immediate parent, if one exists,
- * helps ensure tweet type metrics correctly distinguish roots from non-roots.
- */
- val inReplyToTweetId = ancestors.tail.headOption.map(_.tweetId)
- val parentAncestor = toScoredTweetCandidateFromAncestor(
- ancestor = ancestors.head,
- inReplyToTweetId = inReplyToTweetId,
- conversationId = v1.conversationId,
- ancestors = Some(ancestors.tail),
- candidateTweetSourceId = v1.candidateTweetSourceId
- )
-
- optionallyIncludedRootTweet ++
- Seq((parentAncestor, Some(v1)), (v1, Some(v1)))
-
- case any => Seq((any, None)) // Set focalTweetId to None if not eligible for convo
- }
-
- /**
- * Dedup each tweet keeping the one with highest scored Focal Tweet
- * Focal Tweet ID != the Conversation ID, which is set to the root of the conversation
- * Focal Tweet ID will be defined for tweets with ancestors that should be
- * in conversation modules and None for standalone tweets.
- */
- val sortedDedupedCandidates = candidates
- .groupBy { case (v1, _) => v1.tweetId }
- .mapValues { group =>
- val (candidate, focalTweetOpt) = group.maxBy {
- case (_, Some(focal)) => focal.score
- case (_, None) => 0
- }
- ScoredTweetCandidateWithFocalTweet(candidate, focalTweetOpt.map(focal => focal.tweetId))
- }.values.toSeq.sortBy(_.candidate.tweetId)
-
- CandidatesWithSourceFeatures(
- candidates = sortedDedupedCandidates,
- features = FeatureMapBuilder()
- .add(TimelineScorerCandidateSourceSucceededFeature, true)
- .build()
- )
- }
- }
-
- private def isEligibleReply(candidate: ct.ScoredTweetCandidateAliases.V1Alias): Boolean = {
- candidate.inReplyToTweetId.nonEmpty &&
- !candidate.isRetweet.getOrElse(false) &&
- candidate.ancestors.exists(_.nonEmpty)
- }
-
- /**
- * If we have a retweet, get the source tweet id.
- * If it is not a retweet, get the regular tweet id.
- */
- private def originalTweetId(candidate: ct.ScoredTweetCandidateAliases.V1Alias): Long = {
- candidate.sourceTweetId.getOrElse(candidate.tweetId)
- }
-
- private def toScoredTweetCandidateFromAncestor(
- ancestor: Ancestor,
- inReplyToTweetId: Option[Long],
- conversationId: Option[Long],
- ancestors: Option[Seq[Ancestor]],
- candidateTweetSourceId: Option[CandidateTweetSourceId]
- ): ct.ScoredTweetCandidateAliases.V1Alias = {
- ct.v1.ScoredTweetCandidate(
- tweetId = ancestor.tweetId,
- authorId = ancestor.userId.getOrElse(0L),
- score = 0.0,
- isAncestorCandidate = Some(true),
- inReplyToTweetId = inReplyToTweetId,
- conversationId = conversationId,
- ancestors = ancestors,
- candidateTweetSourceId = candidateTweetSourceId
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD
deleted file mode 100644
index f9453b9a1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala",
- "stitch/stitch-timelineservice/src/main/scala",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-timelineservice/src/main/scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala
deleted file mode 100644
index 053c16a3e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timeline_service
-
-import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature
-import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.timelineservice.TimelineService
-import com.twitter.timelineservice.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-case object TimelineServiceResponseWasTruncatedFeature
- extends FeatureWithDefaultOnFailure[PipelineQuery, Boolean] {
- override val defaultValue: Boolean = false
-}
-
-@Singleton
-class TimelineServiceTweetCandidateSource @Inject() (
- timelineService: TimelineService)
- extends CandidateSourceWithExtractedFeatures[t.TimelineQuery, t.Tweet] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("TimelineServiceTweet")
-
- override def apply(request: t.TimelineQuery): Stitch[CandidatesWithSourceFeatures[t.Tweet]] = {
- timelineService
- .getTimeline(request).map { timeline =>
- val candidates = timeline.entries.collect {
- case t.TimelineEntry.Tweet(tweet) => tweet
- }
-
- val candidateSourceFeatures =
- FeatureMapBuilder()
- .add(TimelineServiceResponseWasTruncatedFeature, timeline.wasTruncated.getOrElse(false))
- .add(PreviousCursorFeature, timeline.responseCursor.flatMap(_.top).getOrElse(""))
- .add(NextCursorFeature, timeline.responseCursor.flatMap(_.bottom).getOrElse(""))
- .build()
-
- CandidatesWithSourceFeatures(candidates = candidates, features = candidateSourceFeatures)
- }
- }
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD
deleted file mode 100644
index 60d486676..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "src/thrift/com/twitter/timelines/impression:thrift-scala",
- "strato/config/columns/timelines/impression-store:impression-store-strato-client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "strato/config/columns/timelines/impression-store:impression-store-strato-client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala
deleted file mode 100644
index 3c4b615bb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.timelines_impression_store
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.timelines.impression_store.TweetImpressionStoreManhattanV2OnUserClientColumn
-import com.twitter.timelines.impression.thriftscala.TweetImpressionsEntries
-import com.twitter.timelines.impression.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelinesImpressionStoreCandidateSourceV2 @Inject() (
- client: TweetImpressionStoreManhattanV2OnUserClientColumn)
- extends StratoKeyFetcherSource[
- Long,
- t.TweetImpressionsEntries,
- t.TweetImpressionsEntry
- ] {
-
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier(
- "TimelinesImpressionStore")
-
- override val fetcher: Fetcher[Long, Unit, TweetImpressionsEntries] = client.fetcher
-
- override def stratoResultTransformer(
- stratoResult: t.TweetImpressionsEntries
- ): Seq[t.TweetImpressionsEntry] =
- stratoResult.entries
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD
deleted file mode 100644
index d145edc44..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "strato/config/columns/interests:interests-strato-client",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala
deleted file mode 100644
index 6b46e1298..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.topics
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSeqSource
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.strato.client.Fetcher
-import com.twitter.strato.generated.client.interests.FollowedTopicsGetterClientColumn
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FollowedTopicsCandidateSource @Inject() (
- column: FollowedTopicsGetterClientColumn)
- extends StratoKeyViewFetcherSeqSource[
- Long,
- Unit,
- Long
- ] {
- override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("FollowedTopics")
-
- override val fetcher: Fetcher[Long, Unit, Seq[Long]] = column.fetcher
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel
deleted file mode 100644
index acfc37015..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala",
- "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala",
- "strato/config/columns/tweetconvosvc:tweetconvosvc-strato-client",
- "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala",
- "tweetconvosvc/thrift/src/main/thrift:thrift-scala",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "strato/config/columns/tweetconvosvc:tweetconvosvc-strato-client",
- "tweetconvosvc/thrift/src/main/thrift:thrift-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala
deleted file mode 100644
index 889a0164d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-import com.twitter.tweetconvosvc.tweet_ancestor.{thriftscala => ta}
-import com.twitter.tweetconvosvc.{thriftscala => tcs}
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import javax.inject.Inject
-import javax.inject.Singleton
-
-case class ConversationServiceCandidateSourceRequest(
- tweetsWithConversationMetadata: Seq[TweetWithConversationMetadata])
-
-case class TweetWithConversationMetadata(
- tweetId: Long,
- userId: Option[Long],
- sourceTweetId: Option[Long],
- sourceUserId: Option[Long],
- inReplyToTweetId: Option[Long],
- conversationId: Option[Long],
- ancestors: Seq[ta.TweetAncestor])
-
-/**
- * Candidate source that fetches ancestors of input candidates from Tweetconvosvc and
- * returns a flattened list of input and ancestor candidates.
- */
-@Singleton
-class ConversationServiceCandidateSource @Inject() (
- conversationServiceClient: tcs.ConversationService.MethodPerEndpoint)
- extends CandidateSourceWithExtractedFeatures[
- ConversationServiceCandidateSourceRequest,
- TweetWithConversationMetadata
- ] {
-
- override val identifier: CandidateSourceIdentifier =
- CandidateSourceIdentifier("ConversationService")
-
- private val maxModuleSize = 3
- private val maxAncestorsInConversation = 2
- private val numberOfRootTweets = 1
- private val maxTweetsInConversationWithSameId = 1
-
- override def apply(
- request: ConversationServiceCandidateSourceRequest
- ): Stitch[CandidatesWithSourceFeatures[TweetWithConversationMetadata]] = {
- val inputTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata] =
- request.tweetsWithConversationMetadata
- val ancestorsRequest =
- tcs.GetAncestorsRequest(inputTweetsWithConversationMetadata.map(_.tweetId))
-
- // build the tweets with conversation metadata by calling the conversation service with reduced
- // ancestors to limit to maxModuleSize
- val tweetsWithConversationMetadataFromAncestors: Stitch[Seq[TweetWithConversationMetadata]] =
- Stitch
- .callFuture(conversationServiceClient.getAncestors(ancestorsRequest))
- .map { getAncestorsResponse: tcs.GetAncestorsResponse =>
- inputTweetsWithConversationMetadata
- .zip(getAncestorsResponse.ancestors).collect {
- case (focalTweet, tcs.TweetAncestorsResult.TweetAncestors(ancestorsResult))
- if ancestorsResult.nonEmpty =>
- getTweetsInThread(focalTweet, ancestorsResult.head)
- }.flatten
- }
-
- // dedupe the tweets in the list and transform the calling error to
- // return the requested tweets with conversation metadata
- val transformedTweetsWithConversationMetadata: Stitch[Seq[TweetWithConversationMetadata]] =
- tweetsWithConversationMetadataFromAncestors.transform {
- case Return(ancestors) =>
- Stitch.value(dedupeCandidates(inputTweetsWithConversationMetadata, ancestors))
- case Throw(_) =>
- Stitch.value(inputTweetsWithConversationMetadata)
- }
-
- // return the candidates with empty source features from transformed tweetsWithConversationMetadata
- transformedTweetsWithConversationMetadata.map {
- responseTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata] =>
- CandidatesWithSourceFeatures(
- responseTweetsWithConversationMetadata,
- FeatureMap.empty
- )
- }
- }
-
- private def getTweetsInThread(
- focalTweet: TweetWithConversationMetadata,
- ancestors: ta.TweetAncestors
- ): Seq[TweetWithConversationMetadata] = {
- // Re-add the focal tweet so we can easily build modules and dedupe later.
- // Note, TweetConvoSVC returns the bottom of the thread first, so we
- // reverse them for easy rendering.
- val focalTweetWithConversationMetadata = TweetWithConversationMetadata(
- tweetId = focalTweet.tweetId,
- userId = focalTweet.userId,
- sourceTweetId = focalTweet.sourceTweetId,
- sourceUserId = focalTweet.sourceUserId,
- inReplyToTweetId = focalTweet.inReplyToTweetId,
- conversationId = Some(focalTweet.tweetId),
- ancestors = ancestors.ancestors
- )
-
- val parentTweets = ancestors.ancestors.map { ancestor =>
- TweetWithConversationMetadata(
- tweetId = ancestor.tweetId,
- userId = Some(ancestor.userId),
- sourceTweetId = None,
- sourceUserId = None,
- inReplyToTweetId = None,
- conversationId = Some(focalTweet.tweetId),
- ancestors = Seq.empty
- )
- } ++ getTruncatedRootTweet(ancestors, focalTweet.tweetId)
-
- val (intermediates, root) = parentTweets.splitAt(parentTweets.size - numberOfRootTweets)
- val truncatedIntermediates =
- intermediates.take(maxModuleSize - maxAncestorsInConversation).reverse
- root ++ truncatedIntermediates :+ focalTweetWithConversationMetadata
- }
-
- /**
- * Ancestor store truncates at 256 ancestors. For very large reply threads, we try best effort
- * to append the root tweet to the ancestor list based on the conversationId and
- * conversationRootAuthorId. When rendering conversation modules, we can display the root tweet
- * instead of the 256th highest ancestor.
- */
- private def getTruncatedRootTweet(
- ancestors: ta.TweetAncestors,
- focalTweetId: Long
- ): Option[TweetWithConversationMetadata] = {
- ancestors.conversationRootAuthorId.collect {
- case rootAuthorId
- if ancestors.state == ta.ReplyState.Partial &&
- ancestors.ancestors.last.tweetId != ancestors.conversationId =>
- TweetWithConversationMetadata(
- tweetId = ancestors.conversationId,
- userId = Some(rootAuthorId),
- sourceTweetId = None,
- sourceUserId = None,
- inReplyToTweetId = None,
- conversationId = Some(focalTweetId),
- ancestors = Seq.empty
- )
- }
- }
-
- private def dedupeCandidates(
- inputTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata],
- ancestors: Seq[TweetWithConversationMetadata]
- ): Seq[TweetWithConversationMetadata] = {
- val dedupedAncestors: Iterable[TweetWithConversationMetadata] = ancestors
- .groupBy(_.tweetId).map {
- case (_, duplicateAncestors)
- if duplicateAncestors.size > maxTweetsInConversationWithSameId =>
- duplicateAncestors.maxBy(_.conversationId.getOrElse(0L))
- case (_, nonDuplicateAncestors) => nonDuplicateAncestors.head
- }
- // Sort by tweet id to prevent issues with future assumptions of the root being the first
- // tweet and the focal being the last tweet in a module. The tweets as a whole do not need
- // to be sorted overall, only the relative order within modules must be kept.
- val sortedDedupedAncestors: Seq[TweetWithConversationMetadata] =
- dedupedAncestors.toSeq.sortBy(_.tweetId)
-
- val ancestorIds = sortedDedupedAncestors.map(_.tweetId).toSet
- val updatedCandidates = inputTweetsWithConversationMetadata.filterNot { candidate =>
- ancestorIds.contains(candidate.tweetId)
- }
- sortedDedupedAncestors ++ updatedCandidates
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala
deleted file mode 100644
index 59a0c725f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc
-
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-import com.twitter.timelineservice.suggests.thriftscala.SuggestType
-
-object AuthorIdFeature extends Feature[TweetCandidate, Option[Long]]
-object AncestorIdsFeature extends Feature[TweetCandidate, Seq[Long]]
-object ConversationModuleFocalTweetIdFeature extends Feature[TweetCandidate, Option[Long]]
-object InReplyToFeature extends Feature[TweetCandidate, Option[Long]]
-object IsRetweetFeature extends Feature[TweetCandidate, Boolean]
-object SourceTweetIdFeature extends Feature[TweetCandidate, Option[Long]]
-object SourceUserIdFeature extends Feature[TweetCandidate, Option[Long]]
-object SuggestTypeFeature extends Feature[TweetCandidate, Option[SuggestType]]
-
-object ConversationServiceResponseFeatureTransformer
- extends CandidateFeatureTransformer[TweetWithConversationMetadata] {
- override val identifier: TransformerIdentifier =
- TransformerIdentifier("ConversationServiceResponse")
-
- override val features: Set[Feature[_, _]] =
- Set(
- AuthorIdFeature,
- InReplyToFeature,
- IsRetweetFeature,
- SourceTweetIdFeature,
- SourceUserIdFeature,
- ConversationModuleFocalTweetIdFeature,
- AncestorIdsFeature,
- SuggestTypeFeature
- )
-
- override def transform(candidate: TweetWithConversationMetadata): FeatureMap = {
- FeatureMapBuilder()
- .add(AuthorIdFeature, candidate.userId)
- .add(InReplyToFeature, candidate.inReplyToTweetId)
- .add(IsRetweetFeature, candidate.sourceTweetId.isDefined)
- .add(SourceTweetIdFeature, candidate.sourceTweetId)
- .add(SourceUserIdFeature, candidate.sourceUserId)
- .add(ConversationModuleFocalTweetIdFeature, candidate.conversationId)
- .add(AncestorIdsFeature, candidate.ancestors.map(_.tweetId))
- .add(SuggestTypeFeature, Some(SuggestType.OrganicConversation))
- .build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala
deleted file mode 100644
index 426adb98c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Takes a conversation module item and truncates it to be at most the focal tweet, the focal tweet's
- * in reply to tweet and optionally, the root conversation tweet if desired.
- * @param pipelineScope What pipeline scopes to include in this.
- * @param includeRootTweet Whether to include the root tweet at the top of the conversation or not.
- * @tparam Query
- */
-case class DropMaxConversationModuleItemCandidates[-Query <: PipelineQuery](
- override val pipelineScope: CandidateScope,
- includeRootTweet: Boolean)
- extends Selector[Query] {
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val updatedCandidates = remainingCandidates.collect {
- case moduleCandidate: ModuleCandidateWithDetails if pipelineScope.contains(moduleCandidate) =>
- updateConversationModule(moduleCandidate, includeRootTweet)
- case candidates => candidates
- }
- SelectorResult(remainingCandidates = updatedCandidates, result = result)
- }
-
- private def updateConversationModule(
- module: ModuleCandidateWithDetails,
- includeRootTweet: Boolean
- ): ModuleCandidateWithDetails = {
- // If the thread is only the root tweet & a focal tweet replying to it, no truncation can be done.
- if (module.candidates.length <= 2) {
- module
- } else {
- // If a thread is more 3 or more tweets, we optionally keep the root tweet if desired, and take
- // the focal tweet tweet and its direct ancestor (the one it would have replied to) and return
- // those.
- val tweetCandidates = module.candidates
- val replyAndFocalTweet = tweetCandidates.takeRight(2)
- val updatedConversation = if (includeRootTweet) {
- tweetCandidates.headOption ++ replyAndFocalTweet
- } else {
- replyAndFocalTweet
- }
- module.copy(candidates = updatedConversation.toSeq)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD
deleted file mode 100644
index 2ed1a6316..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala
deleted file mode 100644
index abe128926..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.slice
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.component_library.model.presentation.slice.SliceItemPresentation
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.decorator.slice.builder.CandidateSliceItemBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.stitch.Stitch
-
-/**
- * Adds a [[Decoration]] for all `candidates` that are [[CursorCandidate]]s
- *
- * @note Only [[CursorCandidate]]s get decorated in [[SliceItemCandidateDecorator]]
- * because the [[com.twitter.product_mixer.component_library.premarshaller.slice.SliceDomainMarshaller]]
- * handles the undecorated non-[[CursorCandidate]] `candidates` directly.
- */
-case class SliceItemCandidateDecorator[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- cursorBuilder: CandidateSliceItemBuilder[Query, CursorCandidate, CursorItem],
- override val identifier: DecoratorIdentifier = DecoratorIdentifier("SliceItemCandidate"))
- extends CandidateDecorator[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[Decoration]] = {
- val cursorPresentations = candidates.collect {
- case CandidateWithFeatures(candidate: CursorCandidate, features) =>
- val cursorItem = cursorBuilder(query, candidate, features)
- val presentation = SliceItemPresentation(sliceItem = cursorItem)
-
- Decoration(candidate, presentation)
- }
-
- Stitch.value(cursorPresentations)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD
deleted file mode 100644
index bbbde90f6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala
deleted file mode 100644
index 307911c85..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.slice.builder
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.component_library.model.candidate.{
- NextCursor => CursorCandidateNextCursor
-}
-import com.twitter.product_mixer.component_library.model.candidate.{
- PreviousCursor => CursorCandidatePreviousCursor
-}
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem
-import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.slice.builder.CandidateSliceItemBuilder
-
-case class CursorCandidateSliceItemBuilder()
- extends CandidateSliceItemBuilder[PipelineQuery, CursorCandidate, CursorItem] {
-
- override def apply(
- query: PipelineQuery,
- candidate: CursorCandidate,
- featureMap: FeatureMap
- ): CursorItem =
- candidate.cursorType match {
- case CursorCandidateNextCursor => CursorItem(candidate.value, NextCursor)
- case CursorCandidatePreviousCursor => CursorItem(candidate.value, PreviousCursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD
deleted file mode 100644
index ea3b7b298..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD
+++ /dev/null
@@ -1,108 +0,0 @@
-scala_library(
- name = "urt",
- sources = ["**/*.scala"] + exclude_globs(["builder/richtext/*.scala"]),
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ":richtext",
- "3rdparty/jvm/com/twitter/bijection:json",
- "3rdparty/jvm/com/twitter/bijection:scrooge",
- "explore/explore-mixer/server/src/main/scala/com/twitter/explore_mixer/model/request",
- "interests-mixer/server/src/main/scala/com/twitter/interests_mixer/model/request",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ads/adserver:ad_metadata_container-scala",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "src/thrift/com/twitter/hermit:hermit-scala",
- "src/thrift/com/twitter/suggests/controller_data:controller_data-scala",
- "src/thrift/com/twitter/timelines/service:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala",
- "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala",
- "stringcenter/client",
- "stringcenter/client/src/main/java",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client",
- "timelines/src/main/scala/com/twitter/timelines/util",
- "trends/trending_content/src/main/scala/com/twitter/trends/trending_content/util:compacting-number-localizer",
- "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala",
- "twitter-text/lib/java/src/main/java/com/twitter/twittertext",
- ],
- exports = [
- ":richtext",
- "3rdparty/jvm/com/twitter/bijection:json",
- "3rdparty/jvm/com/twitter/bijection:scrooge",
- "explore/explore-mixer/server/src/main/scala/com/twitter/explore_mixer/model/request",
- "interests-mixer/server/src/main/scala/com/twitter/interests_mixer/model/request",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ads/adserver:ad_metadata_container-scala",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- "src/thrift/com/twitter/suggests/controller_data:controller_data-scala",
- "src/thrift/com/twitter/timelines/service:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala",
- "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala",
- "stringcenter/client",
- "stringcenter/client/src/main/java",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client",
- "timelines/src/main/scala/com/twitter/timelines/util",
- "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala",
- "twitter-text/lib/java/src/main/java/com/twitter/twittertext",
- ],
-)
-
-scala_library(
- name = "richtext",
- sources = ["builder/richtext/*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "twitter-text/lib/java/src/main/java/com/twitter/twittertext",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "twitter-text/lib/java/src/main/java/com/twitter/twittertext",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala
deleted file mode 100644
index d0a517b2d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.presentation.urt.ConversationModuleItem
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-case class UrtConversationItemCandidateDecorator[
- Query <: PipelineQuery,
- Candidate <: BaseTweetCandidate
-](
- tweetCandidateUrtItemBuilder: TweetCandidateUrtItemBuilder[Query, Candidate],
- override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtConversationItem"))
- extends CandidateDecorator[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[Decoration]] = {
- val candidatePresentations = candidates.view.zipWithIndex.map {
- case (candidate, index) =>
- val itemPresentation = new UrtItemPresentation(
- timelineItem = tweetCandidateUrtItemBuilder(
- pipelineQuery = query,
- tweetCandidate = candidate.candidate,
- candidateFeatures = candidate.features)
- ) with ConversationModuleItem {
- override val treeDisplay: Option[ModuleItemTreeDisplay] = None
- override val dispensable: Boolean = index < candidates.length - 1
- }
-
- Decoration(candidate.candidate, itemPresentation)
- }
-
- Stitch.value(candidatePresentations)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala
deleted file mode 100644
index 81398cd3d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt
-
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.stitch.Stitch
-
-/**
- * Decorator that will apply the provided [[CandidateUrtEntryBuilder]] to each candidate independently to make a [[TimelineItem]]
- */
-case class UrtItemCandidateDecorator[
- Query <: PipelineQuery,
- BuilderInput <: UniversalNoun[Any],
- BuilderOutput <: TimelineItem
-](
- builder: CandidateUrtEntryBuilder[Query, BuilderInput, BuilderOutput],
- override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtItemCandidate"))
- extends CandidateDecorator[Query, BuilderInput] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[BuilderInput]]
- ): Stitch[Seq[Decoration]] = {
- val candidatePresentations = candidates.map { candidate =>
- val itemPresentation = UrtItemPresentation(
- timelineItem = builder(query, candidate.candidate, candidate.features)
- )
-
- Decoration(candidate.candidate, itemPresentation)
- }
-
- Stitch.value(candidatePresentations)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala
deleted file mode 100644
index 928b506b9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt
-
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtModulePresentation
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.stitch.Stitch
-
-/**
- * Decorator that will apply the provided [[urtItemCandidateDecorator]] to all the `candidates` and apply
- * the same [[UrtModulePresentation]] from [[moduleBuilder]] to each Candidate.
- */
-case class UrtItemInModuleDecorator[
- Query <: PipelineQuery,
- BuilderInput <: UniversalNoun[Any],
- BuilderOutput <: TimelineItem
-](
- urtItemCandidateDecorator: CandidateDecorator[Query, BuilderInput],
- moduleBuilder: BaseTimelineModuleBuilder[Query, BuilderInput],
- override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtItemInModule"))
- extends CandidateDecorator[Query, BuilderInput] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[BuilderInput]]
- ): Stitch[Seq[Decoration]] = {
- if (candidates.nonEmpty) {
- val urtItemCandidatesWithDecoration = urtItemCandidateDecorator(query, candidates)
-
- // Pass candidates to support when the module is constructed dynamically based on the list
- val modulePresentation =
- UrtModulePresentation(moduleBuilder(query, candidates))
-
- urtItemCandidatesWithDecoration.map { candidates =>
- candidates.collect {
- case Decoration(candidate, urtItemPresentation: UrtItemPresentation) =>
- Decoration(
- candidate,
- urtItemPresentation.copy(modulePresentation = Some(modulePresentation)))
- }
- }
- } else {
- Stitch.Nil
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala
deleted file mode 100644
index 3c13056b3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt
-
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation
-import com.twitter.product_mixer.component_library.model.presentation.urt.UrtModulePresentation
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.stitch.Stitch
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder
-
-/**
- * Given a [[CandidateWithFeatures]] return the corresponding group with which it should be
- * associated. Returning none will result in the candidate not being assigned to any module.
- */
-trait GroupByKey[-Query <: PipelineQuery, -BuilderInput <: UniversalNoun[Any], Key] {
- def apply(query: Query, candidate: BuilderInput, candidateFeatures: FeatureMap): Option[Key]
-}
-
-/**
- * Similar to [[UrtItemInModuleDecorator]] except that this decorator can assign items to different
- * modules based on the provided [[GroupByKey]].
- *
- * @param urtItemCandidateDecorator decorates individual item candidates
- * @param moduleBuilder builds a module from a particular candidate group
- * @param groupByKey assigns each candidate a module group. Returning [[None]] will result in the
- * candidate not being assigned to a module
- */
-case class UrtMultipleModulesDecorator[
- -Query <: PipelineQuery,
- -BuilderInput <: UniversalNoun[Any],
- GroupKey
-](
- urtItemCandidateDecorator: CandidateDecorator[Query, BuilderInput],
- moduleBuilder: BaseTimelineModuleBuilder[Query, BuilderInput],
- groupByKey: GroupByKey[Query, BuilderInput, GroupKey],
- override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtMultipleModules"))
- extends CandidateDecorator[Query, BuilderInput] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[BuilderInput]]
- ): Stitch[Seq[Decoration]] = {
- if (candidates.nonEmpty) {
-
- /** Individual candidates with [[UrtItemPresentation]]s */
- val decoratedCandidatesStitch: Stitch[
- Seq[(CandidateWithFeatures[BuilderInput], Decoration)]
- ] = urtItemCandidateDecorator(query, candidates).map(candidates.zip(_))
-
- decoratedCandidatesStitch.map { decoratedCandidates =>
- // Group candidates into modules
- val candidatesByModule: Map[Option[GroupKey], Seq[
- (CandidateWithFeatures[BuilderInput], Decoration)
- ]] =
- decoratedCandidates.groupBy {
- case (CandidateWithFeatures(candidate, features), _) =>
- groupByKey(query, candidate, features)
- }
-
- candidatesByModule.iterator.zipWithIndex.flatMap {
-
- // A None group key indicates these candidates should not be put into a module. Return
- // the decorated candidates.
- case ((None, candidateGroup), _) =>
- candidateGroup.map {
- case (_, decoration) => decoration
- }
-
- // Build a UrtModulePresentation and add it to each candidate's decoration.
- case ((_, candidateGroup), index) =>
- val (candidatesWithFeatures, decorations) = candidateGroup.unzip
-
- /**
- * Build the module and update its ID if [[AutomaticUniqueModuleId]]s are being used.
- * Forcing IDs to be different ensures that modules are never accidentally grouped
- * together, since all other fields might otherwise be equal (candidates aren't added
- * to modules until the domain marshalling phase).
- */
- val timelineModule = {
- val module = moduleBuilder(query, candidatesWithFeatures)
-
- ModuleIdGeneration(module.id) match {
- case id: AutomaticUniqueModuleId => module.copy(id = id.withOffset(index).moduleId)
- case _ => module
- }
- }
-
- val modulePresentation = UrtModulePresentation(timelineModule)
-
- decorations.collect {
- case Decoration(candidate, urtItemPresentation: UrtItemPresentation) =>
- Decoration(
- candidate,
- urtItemPresentation.copy(modulePresentation = Some(modulePresentation)))
- }
- }.toSeq
- }
- } else {
- Stitch.Nil
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala
deleted file mode 100644
index 0dd1234fc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.TweetHydrationContext
-
-case class ContextualTweetRefBuilder[-Candidate <: BaseTweetCandidate](
- tweetHydrationContext: TweetHydrationContext) {
-
- def apply(candidate: Candidate): Option[ContextualTweetRef] =
- Some(ContextualTweetRef(candidate.id, Some(tweetHydrationContext)))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala
deleted file mode 100644
index fdb5c4e48..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.conversations
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleConversationMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ConversationModuleMetadataBuilder[
- Query <: PipelineQuery,
- Candidate <: BaseTweetCandidate
-](
- ancestorIdsFeature: Feature[_, Seq[Long]],
- allIdsOrdering: Ordering[Long])
- extends BaseModuleMetadataBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleMetadata = {
-
- val ancestors = candidates.last.features.getOrElse(ancestorIdsFeature, Seq.empty)
- val sortedAllTweetIds = (candidates.last.candidate.id +: ancestors).sorted(allIdsOrdering)
-
- ModuleMetadata(
- adsMetadata = None,
- conversationMetadata = Some(
- ModuleConversationMetadata(
- allTweetIds = Some(sortedAllTweetIds),
- socialContext = None,
- enableDeduplication = Some(true)
- )),
- gridCarouselMetadata = None
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala
deleted file mode 100644
index 2387271da..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.onboarding.injections.thriftscala.Injection
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.OnboardingInjectionConversions._
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptCarouselTileFeature
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptOffsetInModuleFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverFullCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object FlipPromptCandidateUrtItemBuilder {
- val FlipPromptClientEventInfoElement: String = "flip-prompt-message"
-}
-
-case class FlipPromptCandidateUrtItemBuilder[-Query <: PipelineQuery]()
- extends CandidateUrtEntryBuilder[Query, BasePromptCandidate[Any], TimelineItem] {
-
- override def apply(
- query: Query,
- promptCandidate: BasePromptCandidate[Any],
- candidateFeatures: FeatureMap
- ): TimelineItem = {
- val injection = candidateFeatures.get(FlipPromptInjectionsFeature)
-
- injection match {
- case onboardingthrift.Injection.InlinePrompt(candidate) =>
- MessagePromptItem(
- id = promptCandidate.id.toString,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = buildClientEventInfo(injection),
- feedbackActionInfo = candidate.feedbackInfo.map(convertFeedbackInfo),
- isPinned = Some(candidate.isPinnedEntry),
- content = getInlinePromptMessageContent(candidate),
- impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList)
- )
- case onboardingthrift.Injection.FullCover(candidate) =>
- FullCover(
- id = promptCandidate.id.toString,
- // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId
- sortIndex = None,
- clientEventInfo =
- Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)),
- content = getFullCoverContent(candidate)
- )
- case onboardingthrift.Injection.HalfCover(candidate) =>
- HalfCover(
- id = promptCandidate.id.toString,
- // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId
- sortIndex = None,
- clientEventInfo =
- Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)),
- content = getHalfCoverContent(candidate)
- )
- case Injection.TilesCarousel(_) =>
- val offsetInModuleOption =
- candidateFeatures.get(FlipPromptOffsetInModuleFeature)
- val offsetInModule =
- offsetInModuleOption.getOrElse(throw FlipPromptOffsetInModuleMissing)
- val tileOption =
- candidateFeatures.get(FlipPromptCarouselTileFeature)
- val tile = tileOption.getOrElse(throw FlipPromptCarouselTileMissing)
- TilesCarouselConversions.convertTile(tile, offsetInModule)
- case onboardingthrift.Injection.RelevancePrompt(candidate) =>
- PromptItem(
- id = promptCandidate.id.toString,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = buildClientEventInfo(injection),
- content = RelevancePromptConversions.convertContent(candidate),
- impressionCallbacks = Some(candidate.impressionCallbacks.map(convertCallback).toList)
- )
- case _ => throw new UnsupportedFlipPromptException(injection)
- }
- }
-
- private def getInlinePromptMessageContent(
- candidate: onboardingthrift.InlinePrompt
- ): MessageContent = {
- candidate.image match {
- case Some(image) =>
- HeaderImagePromptMessageContent(
- headerImage = convertImage(image),
- headerText = Some(candidate.headerText.text),
- bodyText = candidate.bodyText.map(_.text),
- primaryButtonAction = candidate.primaryAction.map(convertButtonAction),
- secondaryButtonAction = candidate.secondaryAction.map(convertButtonAction),
- headerRichText = Some(convertRichText(candidate.headerText)),
- bodyRichText = candidate.bodyText.map(convertRichText),
- action =
- None
- )
- case None =>
- InlinePromptMessageContent(
- headerText = candidate.headerText.text,
- bodyText = candidate.bodyText.map(_.text),
- primaryButtonAction = candidate.primaryAction.map(convertButtonAction),
- secondaryButtonAction = candidate.secondaryAction.map(convertButtonAction),
- headerRichText = Some(convertRichText(candidate.headerText)),
- bodyRichText = candidate.bodyText.map(convertRichText),
- socialContext = candidate.socialContext.map(convertSocialContext),
- userFacepile = candidate.promptUserFacepile.map(convertUserFacePile)
- )
- }
- }
-
- private def getFullCoverContent(
- candidate: onboardingthrift.FullCover
- ): FullCoverContent =
- FullCoverContent(
- displayType = CoverFullCoverDisplayType,
- primaryText = convertRichText(candidate.primaryText),
- primaryCoverCta = convertCoverCta(candidate.primaryButtonAction),
- secondaryCoverCta = candidate.secondaryButtonAction.map(convertCoverCta),
- secondaryText = candidate.secondaryText.map(convertRichText),
- imageVariant = candidate.image.map(img => convertImageVariant(img.image)),
- details = candidate.detailText.map(convertRichText),
- dismissInfo = candidate.dismissInfo.map(convertDismissInfo),
- imageDisplayType = candidate.image.map(img => convertImageDisplayType(img.imageDisplayType)),
- impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList)
- )
-
- private def getHalfCoverContent(
- candidate: onboardingthrift.HalfCover
- ): HalfCoverContent =
- HalfCoverContent(
- displayType =
- candidate.displayType.map(convertHalfCoverDisplayType).getOrElse(CoverHalfCoverDisplayType),
- primaryText = convertRichText(candidate.primaryText),
- primaryCoverCta = convertCoverCta(candidate.primaryButtonAction),
- secondaryCoverCta = candidate.secondaryButtonAction.map(convertCoverCta),
- secondaryText = candidate.secondaryText.map(convertRichText),
- coverImage = candidate.image.map(convertCoverImage),
- dismissible = candidate.dismissible,
- dismissInfo = candidate.dismissInfo.map(convertDismissInfo),
- impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList)
- )
-
- private def buildClientEventInfo(
- injection: Injection
- ): Option[ClientEventInfo] = {
- injection match {
- //To keep parity between TimelineMixer and Product Mixer, inline prompt switches sets the prompt product identifier as the component and no element. Also includes clientEventDetails
- case onboardingthrift.Injection.InlinePrompt(candidate) =>
- val clientEventDetails: ClientEventDetails =
- ClientEventDetails(
- conversationDetails = None,
- timelinesDetails = Some(TimelinesDetails(injectionType = Some("Message"), None, None)),
- articleDetails = None,
- liveEventDetails = None,
- commerceDetails = None
- )
- Some(
- ClientEventInfo(
- component = candidate.injectionIdentifier,
- element = None,
- details = Some(clientEventDetails),
- action = None,
- entityToken = None))
- // To keep parity between TLM and PM we swap component and elements.
- case onboardingthrift.Injection.RelevancePrompt(candidate) =>
- Some(
- ClientEventInfo(
- // Identifier is prefixed with onboarding per TLM
- component = Some("onboarding_" + candidate.injectionIdentifier),
- element = Some("relevance_prompt"),
- details = None,
- action = None,
- entityToken = None
- ))
-
- case _ => None
- }
- }
-
-}
-
-class UnsupportedFlipPromptException(injection: onboardingthrift.Injection)
- extends UnsupportedOperationException(
- "Unsupported timeline item " + TransportMarshaller.getSimpleName(injection.getClass))
-
-object FlipPromptOffsetInModuleMissing
- extends NoSuchElementException(
- "FlipPromptOffsetInModuleFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource")
-
-object FlipPromptCarouselTileMissing
- extends NoSuchElementException(
- "FlipPromptCarouselTileFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala
deleted file mode 100644
index ab6d21057..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.product_mixer.component_library.decorator.urt.GroupByKey
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptOffsetInModuleFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object FlipPromptModuleGrouping extends GroupByKey[PipelineQuery, UniversalNoun[Any], Int] {
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): Option[Int] = {
- val injection = candidateFeatures.get(FlipPromptInjectionsFeature)
- val offsetInModule = candidateFeatures.getOrElse(FlipPromptOffsetInModuleFeature, None)
-
- // We return None for any candidate that doesn't have an offsetInModule, so that they are left as independent items.
- // Otherwise, we return a hash of the injection instance which will be used to aggregate candidates with matching values into a module.
- offsetInModule.map(_ => injection.hashCode())
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala
deleted file mode 100644
index 00383f6ce..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.onboarding.injections.thriftscala.Injection
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class FlipPromptUrtModuleBuilder[-Query <: PipelineQuery](
- moduleIdGeneration: ModuleIdGeneration = AutomaticUniqueModuleId())
- extends BaseTimelineModuleBuilder[Query, BasePromptCandidate[Any]] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[BasePromptCandidate[Any]]]
- ): TimelineModule = {
- val firstCandidate = candidates.head
- val injection = firstCandidate.features.get(FlipPromptInjectionsFeature)
- injection match {
- case Injection.TilesCarousel(candidate) =>
- TimelineModule(
- id = moduleIdGeneration.moduleId,
- sortIndex = None,
- entryNamespace = EntryNamespace("flip-timeline-module"),
- clientEventInfo =
- Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)),
- feedbackActionInfo =
- candidate.feedbackInfo.map(OnboardingInjectionConversions.convertFeedbackInfo),
- isPinned = Some(candidate.isPinnedEntry),
- // Items are automatically set in the domain marshaller phase
- items = Seq.empty,
- displayType = Carousel,
- header = candidate.header.map(TilesCarouselConversions.convertModuleHeader),
- footer = None,
- metadata = None,
- showMoreBehavior = None
- )
- case _ => throw new UnsupportedFlipPromptInModuleException(injection)
- }
- }
-}
-
-class UnsupportedFlipPromptInModuleException(injection: onboardingthrift.Injection)
- extends UnsupportedOperationException(
- "Unsupported timeline item in a Flip prompt module " + TransportMarshaller.getSimpleName(
- injection.getClass))
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala
deleted file mode 100644
index 92c8d97d7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala
+++ /dev/null
@@ -1,361 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CenterCoverHalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorDismiss
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorNavigate
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCta
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCtaBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverImage
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon._
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.FollowAllMessageActionType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.LargeUserFacepileDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageImage
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Bounce
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Default
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Primary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Secondary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Text
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Destructive
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Neutral
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveSecondary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Dismiss
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FollowGeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FullWidth
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Icon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.IconSmall
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpoint
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpointOptions
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Center
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Natural
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextList
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextMention
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextUser
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong
-
-/***
- * Helper class to convert onboarding thrift to product-mixer models
- */
-object OnboardingInjectionConversions {
-
- def convertFeedbackInfo(
- feedbackInfo: onboardingthrift.FeedbackInfo
- ): FeedbackActionInfo = {
- val actions = feedbackInfo.actions.map {
- case onboardingthrift.FeedbackAction.DismissAction(dismissAction) =>
- FeedbackAction(
- Dismiss,
- prompt = dismissAction.prompt,
- confirmation = dismissAction.confirmation,
- hasUndoAction = dismissAction.hasUndoAction,
- feedbackUrl = dismissAction.feedbackUrl,
- childFeedbackActions =
- None,
- confirmationDisplayType = None,
- clientEventInfo = None,
- icon = None,
- richBehavior = None,
- subprompt = None,
- encodedFeedbackRequest = None
- )
- case onboardingthrift.FeedbackAction.UnknownUnionField(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- FeedbackActionInfo(
- feedbackActions = actions,
- feedbackMetadata = None,
- displayContext = None,
- clientEventInfo = None)
- }
-
- def convertClientEventInfo(input: onboardingthrift.ClientEventInfo): ClientEventInfo =
- ClientEventInfo(
- component = input.component,
- element = input.element,
- details = None,
- action = input.action,
- entityToken = None)
-
- def convertCallback(callback: onboardingthrift.Callback): Callback =
- Callback(callback.endpoint)
-
- def convertImage(image: onboardingthrift.Image): MessageImage =
- MessageImage(
- Set(convertImageVariant(image.image)),
- backgroundColor =
- None
- )
-
- def convertCoverImage(image: onboardingthrift.Image): CoverImage =
- CoverImage(
- convertImageVariant(image.image),
- imageDisplayType = convertImageDisplayType(image.imageDisplayType),
- imageAnimationType = image.imageAnimationType.map(convertImageAnimationType),
- )
-
- def convertImageDisplayType(
- imageDisplayType: onboardingthrift.ImageDisplayType
- ): ImageDisplayType =
- imageDisplayType match {
- case onboardingthrift.ImageDisplayType.Icon => Icon
- case onboardingthrift.ImageDisplayType.FullWidth => FullWidth
- case onboardingthrift.ImageDisplayType.IconSmall => IconSmall
- case onboardingthrift.ImageDisplayType.EnumUnknownImageDisplayType(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- private def convertImageAnimationType(
- imageAnimationType: onboardingthrift.ImageAnimationType
- ): ImageAnimationType =
- imageAnimationType match {
- case onboardingthrift.ImageAnimationType.Bounce => Bounce
- case onboardingthrift.ImageAnimationType.EnumUnknownImageAnimationType(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- def convertImageVariant(imageVariant: onboardingthrift.ImageVariant): ImageVariant =
- ImageVariant(
- url = imageVariant.url,
- width = imageVariant.width,
- height = imageVariant.height,
- palette = None)
-
- def convertButtonAction(
- buttonAction: onboardingthrift.ButtonAction
- ): MessageTextAction =
- MessageTextAction(
- buttonAction.text,
- MessageAction(
- dismissOnClick = buttonAction.dismissOnClick.getOrElse(true),
- url = getActionUrl(buttonAction),
- clientEventInfo = Some(convertClientEventInfo(buttonAction.clientEventInfo)),
- onClickCallbacks = buttonAction.callbacks.map(_.map(convertCallback).toList)
- )
- )
-
- private def getActionUrl(buttonAction: onboardingthrift.ButtonAction) =
- buttonAction.buttonBehavior match {
- case onboardingthrift.ButtonBehavior.Navigate(navigate) => Some(navigate.url.url)
- case onboardingthrift.ButtonBehavior.Dismiss(_) => None
- case onboardingthrift.ButtonBehavior.UnknownUnionField(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- def convertRichText(
- richText: com.twitter.onboarding.injections.thriftscala.RichText
- ): RichText = {
- val entities = richText.entities.map(entity =>
- RichTextEntity(
- entity.fromIndex,
- entity.toIndex,
- entity.ref.map(convertRef),
- entity.format.map(convertFormat)))
- RichText(
- text = richText.text,
- entities = entities.toList,
- rtl = richText.rtl,
- alignment = richText.alignment.map(convertAlignment))
- }
-
- private def convertAlignment(alignment: onboardingthrift.RichTextAlignment): RichTextAlignment =
- alignment match {
- case onboardingthrift.RichTextAlignment.Natural => Natural
- case onboardingthrift.RichTextAlignment.Center => Center
- case onboardingthrift.RichTextAlignment.EnumUnknownRichTextAlignment(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- private def convertRef(ref: onboardingthrift.ReferenceObject): ReferenceObject =
- ref match {
- case onboardingthrift.ReferenceObject.User(user) => RichTextUser(user.id)
- case onboardingthrift.ReferenceObject.Mention(mention) =>
- RichTextMention(mention.id, mention.screenName)
- case onboardingthrift.ReferenceObject.Hashtag(hashtag) => RichTextHashtag(hashtag.text)
-
- case onboardingthrift.ReferenceObject.Cashtag(cashtag) => RichTextCashtag(cashtag.text)
- case onboardingthrift.ReferenceObject.TwitterList(twList) =>
- RichTextList(twList.id, twList.url)
- case onboardingthrift.ReferenceObject.Url(url) => RichTextHashtag(url.url)
- case onboardingthrift.ReferenceObject.UnknownUnionField(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- private def convertFormat(format: onboardingthrift.RichTextFormat): RichTextFormat =
- format match {
- case onboardingthrift.RichTextFormat.Plain => Plain
- case onboardingthrift.RichTextFormat.Strong => Strong
- case onboardingthrift.RichTextFormat.EnumUnknownRichTextFormat(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- // Specific to Message prompt
- def convertSocialContext(socialContext: onboardingthrift.RichText): SocialContext =
- GeneralContext(
- contextType = FollowGeneralContextType,
- text = socialContext.text,
- url = None,
- contextImageUrls = None,
- landingUrl = None)
-
- def convertUserFacePile(
- userFacepile: onboardingthrift.PromptUserFacepile
- ): UserFacepile =
- UserFacepile(
- userIds = userFacepile.userIds.toList,
- featuredUserIds = userFacepile.featuredUserIds.toList,
- action = userFacepile.action.map(convertButtonAction),
- actionType = userFacepile.actionType.map(convertUserFacePileActionType),
- displaysFeaturingText = userFacepile.displaysFeaturingText,
- displayType = Some(LargeUserFacepileDisplayType)
- )
-
- private def convertUserFacePileActionType(
- actionType: onboardingthrift.FacepileActionType
- ): MessageActionType =
- actionType match {
- case onboardingthrift.FacepileActionType.FollowAll => FollowAllMessageActionType
- case onboardingthrift.FacepileActionType.EnumUnknownFacepileActionType(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- // Specific to Cover
-
- def convertHalfCoverDisplayType(
- displayType: onboardingthrift.HalfCoverDisplayType
- ): HalfCoverDisplayType =
- displayType match {
- case onboardingthrift.HalfCoverDisplayType.Cover => CoverHalfCoverDisplayType
- case onboardingthrift.HalfCoverDisplayType.CenterCover =>
- CenterCoverHalfCoverDisplayType
- case onboardingthrift.HalfCoverDisplayType.EnumUnknownHalfCoverDisplayType(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- def convertDismissInfo(dismissInfo: onboardingthrift.DismissInfo): DismissInfo =
- DismissInfo(dismissInfo.callbacks.map(_.map(convertCallback)))
-
- def convertCoverCta(
- buttonAction: onboardingthrift.ButtonAction
- ): CoverCta =
- CoverCta(
- buttonAction.text,
- ctaBehavior = convertCoverCtaBehavior(buttonAction.buttonBehavior),
- callbacks = buttonAction.callbacks.map(_.map(convertCallback).toList),
- clientEventInfo = Some(convertClientEventInfo(buttonAction.clientEventInfo)),
- icon = buttonAction.icon.map(covertHorizonIcon),
- buttonStyle = buttonAction.buttonStyle.map(covertButtonStyle)
- )
-
- private def convertCoverCtaBehavior(
- behavior: onboardingthrift.ButtonBehavior
- ): CoverCtaBehavior =
- behavior match {
- case onboardingthrift.ButtonBehavior.Navigate(navigate) =>
- CoverBehaviorNavigate(convertUrl(navigate.url))
- case onboardingthrift.ButtonBehavior.Dismiss(dismiss) =>
- CoverBehaviorDismiss(dismiss.feedbackMessage.map(convertRichText))
- case onboardingthrift.ButtonBehavior.UnknownUnionField(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- private def covertButtonStyle(bStyle: onboardingthrift.CtaButtonStyle): ButtonStyle =
- bStyle match {
- case onboardingthrift.CtaButtonStyle.Default => Default
- case onboardingthrift.CtaButtonStyle.Primary => Primary
- case onboardingthrift.CtaButtonStyle.Secondary => Secondary
- case onboardingthrift.CtaButtonStyle.Text => Text
- case onboardingthrift.CtaButtonStyle.Destructive => Destructive
- case onboardingthrift.CtaButtonStyle.Neutral => Neutral
- case onboardingthrift.CtaButtonStyle.DestructiveSecondary => DestructiveSecondary
- case onboardingthrift.CtaButtonStyle.DestructiveText => DestructiveText
- case onboardingthrift.CtaButtonStyle.EnumUnknownCtaButtonStyle(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
-
- private def covertHorizonIcon(icon: onboardingthrift.HorizonIcon): HorizonIcon =
- icon match {
- case onboardingthrift.HorizonIcon.Bookmark => Bookmark
- case onboardingthrift.HorizonIcon.Moment => Moment
- case onboardingthrift.HorizonIcon.Debug => Debug
- case onboardingthrift.HorizonIcon.Error => Error
- case onboardingthrift.HorizonIcon.Follow => Follow
- case onboardingthrift.HorizonIcon.Unfollow => Unfollow
- case onboardingthrift.HorizonIcon.Smile => Smile
- case onboardingthrift.HorizonIcon.Frown => Frown
- case onboardingthrift.HorizonIcon.Help => Help
- case onboardingthrift.HorizonIcon.Link => Link
- case onboardingthrift.HorizonIcon.Message => Message
- case onboardingthrift.HorizonIcon.No => No
- case onboardingthrift.HorizonIcon.Outgoing => Outgoing
- case onboardingthrift.HorizonIcon.Pin => Pin
- case onboardingthrift.HorizonIcon.Retweet => Retweet
- case onboardingthrift.HorizonIcon.Speaker => Speaker
- case onboardingthrift.HorizonIcon.Trashcan => Trashcan
- case onboardingthrift.HorizonIcon.Feedback => Feedback
- case onboardingthrift.HorizonIcon.FeedbackClose => FeedbackClose
- case onboardingthrift.HorizonIcon.EyeOff => EyeOff
- case onboardingthrift.HorizonIcon.Moderation => Moderation
- case onboardingthrift.HorizonIcon.Topic => Topic
- case onboardingthrift.HorizonIcon.TopicClose => TopicClose
- case onboardingthrift.HorizonIcon.Flag => Flag
- case onboardingthrift.HorizonIcon.TopicFilled => TopicFilled
- case onboardingthrift.HorizonIcon.NotificationsFollow => NotificationsFollow
- case onboardingthrift.HorizonIcon.Person => Person
- case onboardingthrift.HorizonIcon.Logo => Logo
- case onboardingthrift.HorizonIcon.EnumUnknownHorizonIcon(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
-
- }
-
- def convertUrl(url: onboardingthrift.Url): Url = {
- val urlType = url.urlType match {
- case onboardingthrift.UrlType.ExternalUrl => ExternalUrl
- case onboardingthrift.UrlType.DeepLink => DeepLink
- case onboardingthrift.UrlType.UrtEndpoint => UrtEndpoint
- case onboardingthrift.UrlType.EnumUnknownUrlType(value) =>
- throw new UnsupportedOperationException(s"Unknown product: $value")
- }
- Url(urlType, url.url, url.urtEndpointOptions.map(convertUrtEndpointOptions))
- }
-
- private def convertUrtEndpointOptions(
- urtEndpointOptions: onboardingthrift.UrtEndpointOptions
- ): UrtEndpointOptions =
- UrtEndpointOptions(
- requestParams = urtEndpointOptions.requestParams.map(_.toMap),
- title = urtEndpointOptions.title,
- cacheId = urtEndpointOptions.cacheId,
- subtitle = urtEndpointOptions.subtitle
- )
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala
deleted file mode 100644
index 78e69ee3e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Compact
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Large
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Normal
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-
-/***
- * Helper class to convert Relevance Prompt related onboarding thrift to product-mixer models
- */
-object RelevancePromptConversions {
- def convertContent(
- candidate: onboardingthrift.RelevancePrompt
- ): RelevancePromptContent =
- RelevancePromptContent(
- displayType = convertDisplayType(candidate.displayType),
- title = candidate.title.text,
- confirmation = buildConfirmation(candidate),
- isRelevantText = candidate.isRelevantButton.text,
- notRelevantText = candidate.notRelevantButton.text,
- isRelevantCallback = convertCallbacks(candidate.isRelevantButton.callbacks),
- notRelevantCallback = convertCallbacks(candidate.notRelevantButton.callbacks),
- isRelevantFollowUp = None,
- notRelevantFollowUp = None
- )
-
- // Based on com.twitter.timelinemixer.injection.model.candidate.OnboardingRelevancePromptDisplayType#fromThrift
- def convertDisplayType(
- displayType: onboardingthrift.RelevancePromptDisplayType
- ): RelevancePromptDisplayType =
- displayType match {
- case onboardingthrift.RelevancePromptDisplayType.Normal => Normal
- case onboardingthrift.RelevancePromptDisplayType.Compact => Compact
- case onboardingthrift.RelevancePromptDisplayType.Large => Large
- case onboardingthrift.RelevancePromptDisplayType
- .EnumUnknownRelevancePromptDisplayType(value) =>
- throw new UnsupportedOperationException(s"Unknown display type: $value")
- }
-
- // Based on com.twitter.timelinemixer.injection.model.injection.OnboardingRelevancePromptInjection#buildConfirmation
- def buildConfirmation(candidate: onboardingthrift.RelevancePrompt): String = {
- val isRelevantTextConfirmation =
- buttonToDismissFeedbackText(candidate.isRelevantButton).getOrElse("")
- val notRelevantTextConfirmation =
- buttonToDismissFeedbackText(candidate.notRelevantButton).getOrElse("")
- if (isRelevantTextConfirmation != notRelevantTextConfirmation)
- throw new IllegalArgumentException(
- s"""confirmation text not consistent for two buttons, :
- isRelevantConfirmation: ${isRelevantTextConfirmation}
- notRelevantConfirmation: ${notRelevantTextConfirmation}
- """
- )
- isRelevantTextConfirmation
- }
-
- // Based on com.twitter.timelinemixer.injection.model.candidate.OnboardingInjectionAction#fromThrift
- def buttonToDismissFeedbackText(button: onboardingthrift.ButtonAction): Option[String] = {
- button.buttonBehavior match {
- case onboardingthrift.ButtonBehavior.Dismiss(d) => d.feedbackMessage.map(_.text)
- case _ => None
- }
- }
-
- // Based on com.twitter.timelinemixer.injection.model.injection.OnboardingRelevancePromptInjection#buildCallback
- def convertCallbacks(onboardingCallbacks: Option[Seq[onboardingthrift.Callback]]): Callback = {
- OnboardingInjectionConversions.convertCallback(
- onboardingCallbacks
- .flatMap(_.headOption)
- .getOrElse(
- throw new NoSuchElementException(s"Callback must be provided for the Relevance Prompt")
- ))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala
deleted file mode 100644
index dd4ce7c75..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala
+++ /dev/null
@@ -1,154 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline
-
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.OnboardingInjectionConversions.convertImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.BlackRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ClearRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepGrayRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepGreenRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepOrangeRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepPurpleRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepRedRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepYellowRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedGrayRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedGreenRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedOrangeRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedPurpleRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedRedRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedYellowRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FaintBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FaintGrayRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightGrayRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightGreenRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightOrangeRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightPurpleRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightRedRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightYellowRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumGrayRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumGreenRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumOrangeRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumPurpleRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumRedRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumYellowRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TextBlackRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TextBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TwitterBlueRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.WhiteRosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-
-object TilesCarouselConversions {
- // Tiles Carousel Conversions
- def convertTile(tile: onboardingthrift.Tile, id: Long): TileItem = {
- tile.content match {
- case standard: onboardingthrift.TileContent.Standard =>
- TileItem(
- id = id,
- sortIndex = None,
- clientEventInfo =
- Some(OnboardingInjectionConversions.convertClientEventInfo(tile.clientEventInfo)),
- feedbackActionInfo = None,
- title = standard.standard.title,
- supportingText = "",
- url = tile.url.map(OnboardingInjectionConversions.convertUrl),
- image = tile.image.map(img => convertImageVariant(img.image)),
- content = StandardTileContent(
- title = standard.standard.title,
- supportingText = "",
- badge = standard.standard.badge.map(convertTileBadge)
- )
- )
- case cta: onboardingthrift.TileContent.CallToAction =>
- TileItem(
- id = id,
- sortIndex = None,
- clientEventInfo =
- Some(OnboardingInjectionConversions.convertClientEventInfo(tile.clientEventInfo)),
- feedbackActionInfo = None,
- title = cta.callToAction.text,
- supportingText = "",
- url = tile.url.map(OnboardingInjectionConversions.convertUrl),
- image = None,
- content = CallToActionTileContent(
- text = cta.callToAction.text,
- richText = None,
- ctaButton = None
- )
- )
- case _ =>
- throw new UnsupportedTileCarouselConversionException(s"Tile Content: ${tile.content}")
- }
- }
-
- private def convertTileBadge(badge: onboardingthrift.Badge): Badge = {
- Badge(
- text = badge.text,
- textColorName = badge.textColor.map(convertRosettaColor),
- backgroundColorName = badge.backgroundColor.map(convertRosettaColor))
- }
-
- def convertModuleHeader(header: onboardingthrift.TilesCarouselHeader): ModuleHeader = {
- ModuleHeader(header.header, None, None, None, None, Classic)
- }
-
- private def convertRosettaColor(color: onboardingthrift.RosettaColor): RosettaColor =
- color match {
- case onboardingthrift.RosettaColor.White => WhiteRosettaColor
- case onboardingthrift.RosettaColor.Black => BlackRosettaColor
- case onboardingthrift.RosettaColor.Clear => ClearRosettaColor
- case onboardingthrift.RosettaColor.TextBlack => TextBlackRosettaColor
- case onboardingthrift.RosettaColor.TextBlue => TextBlueRosettaColor
-
- case onboardingthrift.RosettaColor.DeepGray => DeepGrayRosettaColor
- case onboardingthrift.RosettaColor.MediumGray => MediumGrayRosettaColor
- case onboardingthrift.RosettaColor.LightGray => LightGrayRosettaColor
- case onboardingthrift.RosettaColor.FadedGray => FadedGrayRosettaColor
- case onboardingthrift.RosettaColor.FaintGray => FaintGrayRosettaColor
-
- case onboardingthrift.RosettaColor.DeepOrange => DeepOrangeRosettaColor
- case onboardingthrift.RosettaColor.MediumOrange => MediumOrangeRosettaColor
- case onboardingthrift.RosettaColor.LightOrange => LightOrangeRosettaColor
- case onboardingthrift.RosettaColor.FadedOrange => FadedOrangeRosettaColor
-
- case onboardingthrift.RosettaColor.DeepYellow => DeepYellowRosettaColor
- case onboardingthrift.RosettaColor.MediumYellow => MediumYellowRosettaColor
- case onboardingthrift.RosettaColor.LightYellow => LightYellowRosettaColor
- case onboardingthrift.RosettaColor.FadedYellow => FadedYellowRosettaColor
-
- case onboardingthrift.RosettaColor.DeepGreen => DeepGreenRosettaColor
- case onboardingthrift.RosettaColor.MediumGreen => MediumGreenRosettaColor
- case onboardingthrift.RosettaColor.LightGreen => LightGreenRosettaColor
- case onboardingthrift.RosettaColor.FadedGreen => FadedGreenRosettaColor
-
- case onboardingthrift.RosettaColor.DeepBlue => DeepBlueRosettaColor
- case onboardingthrift.RosettaColor.TwitterBlue => TwitterBlueRosettaColor
- case onboardingthrift.RosettaColor.LightBlue => LightBlueRosettaColor
- case onboardingthrift.RosettaColor.FadedBlue => FadedBlueRosettaColor
- case onboardingthrift.RosettaColor.FaintBlue => FaintBlueRosettaColor
-
- case onboardingthrift.RosettaColor.DeepPurple => DeepPurpleRosettaColor
- case onboardingthrift.RosettaColor.MediumPurple => MediumPurpleRosettaColor
- case onboardingthrift.RosettaColor.LightPurple => LightPurpleRosettaColor
- case onboardingthrift.RosettaColor.FadedPurple => FadedPurpleRosettaColor
-
- case onboardingthrift.RosettaColor.DeepRed => DeepRedRosettaColor
- case onboardingthrift.RosettaColor.MediumRed => MediumRedRosettaColor
- case onboardingthrift.RosettaColor.LightRed => LightRedRosettaColor
- case onboardingthrift.RosettaColor.FadedRed => FadedRedRosettaColor
- case onboardingthrift.RosettaColor.EnumUnknownRosettaColor(i) =>
- throw new UnknownThriftEnumException("RosettaColor")
- }
- class UnknownThriftEnumException(enumName: String)
- extends Exception(s"Unknown Thrift Enum Found: ${enumName}")
-
- class UnsupportedTileCarouselConversionException(UnsupportedTileType: String)
- extends Exception(s"Unsupported Tile Type Found: ${UnsupportedTileType}")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala
deleted file mode 100644
index dd9a59e6c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.icon
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon.BaseHorizonIconBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class HorizonIconBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- icon: HorizonIcon)
- extends BaseHorizonIconBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[HorizonIcon] = Some(icon)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala
deleted file mode 100644
index 1593485fc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,274 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad
-
-import com.twitter.ads.adserver.{thriftscala => ads}
-import com.twitter.adserver.{thriftscala => adserver}
-import com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref.ContextualTweetRefBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder.TweetClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.AdMetadataContainer
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Amplify
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.CallToAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.ClickTrackingInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DcmUrlOverrideType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DirectSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerIssue
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerPolitical
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DynamicPrerollType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Earned
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.IndirectSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Issue
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.LiveTvEvent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Marketplace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.MediaInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoDisclosure
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoSponsorshipSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Political
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Preroll
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SkAdNetworkData
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UnknownUrlOverrideType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.VideoVariant
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.util.AdMetadataContainerSerializer
-import com.twitter.timelines.util.PrerollMetadataSerializer
-
-/**
- * [[AdsCandidateUrtItemBuilder]] takes a [[AdsCandidate]] (with a [[Query]] as additional context)
- * and converts it into the Product Mixer URT representation, or throws an error.
- *
- * Currently, the only supported form for URT representation of the [[AdsCandidate]] is a [[Tweet]],
- * but in the future it could be expanded to handle other forms of ads.
- *
- * @param tweetClientEventInfoBuilder Optionally, provide a ClientEventInfoBuilder for Tweets
- * that given an AdsTweetCandidate and element of "tweet".
- * @param tweetDisplayType Should be [[EmphasizedPromotedTweet]] on Profile timelines,
- * otherwise [[Tweet]]
- */
-case class AdsCandidateUrtItemBuilder[Query <: PipelineQuery](
- tweetClientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, AdsTweetCandidate]] = None,
- contextualTweetRefBuilder: Option[ContextualTweetRefBuilder[AdsTweetCandidate]] = None,
- tweetDisplayType: TweetDisplayType = Tweet)
- extends CandidateUrtEntryBuilder[Query, AdsCandidate, TimelineItem] {
-
- override def apply(
- pipelineQuery: Query,
- candidate: AdsCandidate,
- candidateFeatures: FeatureMap
- ): TimelineItem = {
- candidate match {
- case tweetCandidate: AdsTweetCandidate =>
- TweetItem(
- id = tweetCandidate.id,
- entryNamespace = TweetItem.PromotedTweetEntryNamespace,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = tweetClientEventInfoBuilder.flatMap(
- _.apply(
- pipelineQuery,
- tweetCandidate,
- candidateFeatures,
- Some(TweetClientEventInfoElement))),
- feedbackActionInfo = None,
- isPinned = None,
- entryIdToReplace = None,
- socialContext = None,
- highlights = None,
- innerTombstoneInfo = None,
- timelinesScoreInfo = None,
- hasModeratedReplies = None,
- forwardPivot = None,
- innerForwardPivot = None,
- conversationAnnotation = None,
- promotedMetadata = Some(promotedMetadata(tweetCandidate.adImpression)),
- displayType = tweetDisplayType,
- contextualTweetRef = contextualTweetRefBuilder.flatMap(_.apply(tweetCandidate)),
- prerollMetadata = prerollMetadata(tweetCandidate.adImpression),
- replyBadge = None,
- destination = None
- )
- }
- }
-
- private def promotedMetadata(impression: adserver.AdImpression) = {
- PromotedMetadata(
- advertiserId = impression.advertiserId,
- impressionString = impression.impressionString,
- disclosureType = impression.disclosureType.map(convertDisclosureType),
- experimentValues = impression.experimentValues.map(_.toMap),
- promotedTrendId = impression.promotedTrendId.map(_.toLong),
- promotedTrendName = impression.promotedTrendName,
- promotedTrendQueryTerm = impression.promotedTrendQueryTerm,
- promotedTrendDescription = impression.promotedTrendDescription,
- clickTrackingInfo = impression.clickTrackingInfo.map(convertClickTrackingInfo),
- adMetadataContainer = adMetadataContainer(impression)
- )
- }
-
- private def convertDisclosureType(
- disclosureType: adserver.DisclosureType
- ): DisclosureType = disclosureType match {
- case adserver.DisclosureType.None => NoDisclosure
- case adserver.DisclosureType.Political => Political
- case adserver.DisclosureType.Earned => Earned
- case adserver.DisclosureType.Issue => Issue
- case _ => throw new UnsupportedDisclosureTypeException(disclosureType)
- }
-
- private def convertClickTrackingInfo(
- clickTracking: adserver.ClickTrackingInfo
- ): ClickTrackingInfo = ClickTrackingInfo(
- urlParams = clickTracking.urlParams.getOrElse(Map.empty),
- urlOverride = clickTracking.urlOverride,
- urlOverrideType = clickTracking.urlOverrideType.map {
- case adserver.UrlOverrideType.Unknown => UnknownUrlOverrideType
- case adserver.UrlOverrideType.Dcm => DcmUrlOverrideType
- case _ => throw new UnsupportedClickTrackingInfoException(clickTracking)
- }
- )
-
- private def prerollMetadata(adImpression: adserver.AdImpression): Option[PrerollMetadata] = {
- adImpression.serializedPrerollMetadata
- .flatMap(PrerollMetadataSerializer.deserialize).map { metadata =>
- PrerollMetadata(
- metadata.preroll.map(convertPreroll),
- metadata.videoAnalyticsScribePassthrough
- )
- }
- }
-
- private def adMetadataContainer(
- adImpression: adserver.AdImpression
- ): Option[AdMetadataContainer] = {
- adImpression.serializedAdMetadataContainer
- .flatMap(AdMetadataContainerSerializer.deserialize).map { container =>
- AdMetadataContainer(
- removePromotedAttributionForPreroll = container.removePromotedAttributionForPreroll,
- sponsorshipCandidate = container.sponsorshipCandidate,
- sponsorshipOrganization = container.sponsorshipOrganization,
- sponsorshipOrganizationWebsite = container.sponsorshipOrganizationWebsite,
- sponsorshipType = container.sponsorshipType.map(convertSponsorshipType),
- disclaimerType = container.disclaimerType.map(convertDisclaimerType),
- skAdNetworkDataList = container.skAdNetworkDataList.map(convertSkAdNetworkDataList),
- unifiedCardOverride = container.unifiedCardOverride
- )
- }
- }
-
- private def convertSponsorshipType(
- sponsorshipType: ads.SponsorshipType
- ): SponsorshipType = sponsorshipType match {
- case ads.SponsorshipType.Direct => DirectSponsorshipType
- case ads.SponsorshipType.Indirect => IndirectSponsorshipType
- case ads.SponsorshipType.NoSponsorship => NoSponsorshipSponsorshipType
- // Thrift has extras (e.g. Sponsorship4) that are not used in practice
- case _ => throw new UnsupportedSponsorshipTypeException(sponsorshipType)
- }
-
- private def convertDisclaimerType(
- disclaimerType: ads.DisclaimerType
- ): DisclaimerType = disclaimerType match {
- case ads.DisclaimerType.Political => DisclaimerPolitical
- case ads.DisclaimerType.Issue => DisclaimerIssue
- case _ => throw new UnsupportedDisclaimerTypeException(disclaimerType)
- }
-
- private def convertDynamicPrerollType(
- dynamicPrerollType: ads.DynamicPrerollType
- ): DynamicPrerollType =
- dynamicPrerollType match {
- case ads.DynamicPrerollType.Amplify => Amplify
- case ads.DynamicPrerollType.Marketplace => Marketplace
- case ads.DynamicPrerollType.LiveTvEvent => LiveTvEvent
- case _ => throw new UnsupportedDynamicPrerollTypeException(dynamicPrerollType)
- }
-
- private def convertMediaInfo(mediaInfo: ads.MediaInfo): MediaInfo = {
- MediaInfo(
- uuid = mediaInfo.uuid,
- publisherId = mediaInfo.publisherId,
- callToAction = mediaInfo.callToAction.map(convertCallToAction),
- durationMillis = mediaInfo.durationMillis,
- videoVariants = mediaInfo.videoVariants.map(convertVideoVariants),
- advertiserName = mediaInfo.advertiserName,
- renderAdByAdvertiserName = mediaInfo.renderAdByAdvertiserName,
- advertiserProfileImageUrl = mediaInfo.advertiserProfileImageUrl
- )
- }
-
- private def convertVideoVariants(videoVariants: Seq[ads.VideoVariant]): Seq[VideoVariant] = {
- videoVariants.map(videoVariant =>
- VideoVariant(
- url = videoVariant.url,
- contentType = videoVariant.contentType,
- bitrate = videoVariant.bitrate
- ))
- }
-
- private def convertCallToAction(callToAction: ads.CallToAction): CallToAction = {
- CallToAction(
- callToActionType = callToAction.callToActionType,
- url = callToAction.url
- )
- }
-
- private def convertPreroll(
- preroll: ads.Preroll
- ): Preroll = {
- Preroll(
- preroll.prerollId,
- preroll.dynamicPrerollType.map(convertDynamicPrerollType),
- preroll.mediaInfo.map(convertMediaInfo)
- )
- }
-
- private def convertSkAdNetworkDataList(
- skAdNetworkDataList: Seq[ads.SkAdNetworkData]
- ): Seq[SkAdNetworkData] = skAdNetworkDataList.map(sdAdNetwork =>
- SkAdNetworkData(
- version = sdAdNetwork.version,
- srcAppId = sdAdNetwork.srcAppId,
- dstAppId = sdAdNetwork.dstAppId,
- adNetworkId = sdAdNetwork.adNetworkId,
- campaignId = sdAdNetwork.campaignId,
- impressionTimeInMillis = sdAdNetwork.impressionTimeInMillis,
- nonce = sdAdNetwork.nonce,
- signature = sdAdNetwork.signature,
- fidelityType = sdAdNetwork.fidelityType
- ))
-}
-
-class UnsupportedClickTrackingInfoException(clickTrackingInfo: adserver.ClickTrackingInfo)
- extends UnsupportedOperationException(
- s"Unsupported ClickTrackingInfo: $clickTrackingInfo"
- )
-
-class UnsupportedDisclaimerTypeException(disclaimerType: ads.DisclaimerType)
- extends UnsupportedOperationException(
- s"Unsupported DisclaimerType: $disclaimerType"
- )
-
-class UnsupportedDisclosureTypeException(disclosureType: adserver.DisclosureType)
- extends UnsupportedOperationException(
- s"Unsupported DisclosureType: $disclosureType"
- )
-
-class UnsupportedDynamicPrerollTypeException(dynamicPrerollType: ads.DynamicPrerollType)
- extends UnsupportedOperationException(
- s"Unsupported DynamicPrerollType: $dynamicPrerollType"
- )
-
-class UnsupportedSponsorshipTypeException(sponsorshipType: ads.SponsorshipType)
- extends UnsupportedOperationException(
- s"Unsupported SponsorshipType: $sponsorshipType"
- )
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala
deleted file mode 100644
index 0a4e76319..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseDurationBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-import com.twitter.util.Duration
-
-case class DurationParamBuilder(
- durationParam: Param[Duration])
- extends BaseDurationBuilder[PipelineQuery] {
-
- def apply(
- query: PipelineQuery,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): Option[Duration] =
- Some(query.params(durationParam))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala
deleted file mode 100644
index d2028181c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert.ShowAlertCandidateUrtItemBuilder.ShowAlertClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseDurationBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertColorConfigurationBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertDisplayLocationBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertIconDisplayInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertNavigationMetadataBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertUserIdsBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType
-
-object ShowAlertCandidateUrtItemBuilder {
- val ShowAlertClientEventInfoElement: String = "showAlert"
-}
-
-case class ShowAlertCandidateUrtItemBuilder[-Query <: PipelineQuery](
- alertType: ShowAlertType,
- displayLocationBuilder: BaseShowAlertDisplayLocationBuilder[Query],
- colorConfigBuilder: BaseShowAlertColorConfigurationBuilder[Query],
- triggerDelayBuilder: Option[BaseDurationBuilder[Query]] = None,
- displayDurationBuilder: Option[BaseDurationBuilder[Query]] = None,
- clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, ShowAlertCandidate]] = None,
- collapseDelayBuilder: Option[BaseDurationBuilder[Query]] = None,
- userIdsBuilder: Option[BaseShowAlertUserIdsBuilder[Query]] = None,
- richTextBuilder: Option[BaseRichTextBuilder[Query, ShowAlertCandidate]] = None,
- iconDisplayInfoBuilder: Option[BaseShowAlertIconDisplayInfoBuilder[Query]] = None,
- navigationMetadataBuilder: Option[BaseShowAlertNavigationMetadataBuilder[Query]] = None)
- extends CandidateUrtEntryBuilder[
- Query,
- ShowAlertCandidate,
- ShowAlert
- ] {
-
- override def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap,
- ): ShowAlert = ShowAlert(
- id = candidate.id,
- sortIndex = None,
- alertType = alertType,
- triggerDelay = triggerDelayBuilder.flatMap(_.apply(query, candidate, features)),
- displayDuration = displayDurationBuilder.flatMap(_.apply(query, candidate, features)),
- clientEventInfo = clientEventInfoBuilder.flatMap(
- _.apply(query, candidate, features, Some(ShowAlertClientEventInfoElement))),
- collapseDelay = collapseDelayBuilder.flatMap(_.apply(query, candidate, features)),
- userIds = userIdsBuilder.flatMap(_.apply(query, candidate, features)),
- richText = richTextBuilder.map(_.apply(query, candidate, features)),
- iconDisplayInfo = iconDisplayInfoBuilder.flatMap(_.apply(query, candidate, features)),
- displayLocation = displayLocationBuilder(query, candidate, features),
- colorConfig = colorConfigBuilder(query, candidate, features),
- navigationMetadata = navigationMetadataBuilder.flatMap(_.apply(query, candidate, features)),
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala
deleted file mode 100644
index 322d16401..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertColorConfigurationBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticShowAlertColorConfigurationBuilder[-Query <: PipelineQuery](
- configuration: ShowAlertColorConfiguration)
- extends BaseShowAlertColorConfigurationBuilder[Query] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): ShowAlertColorConfiguration = configuration
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala
deleted file mode 100644
index 74ea989dd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertDisplayLocationBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticShowAlertDisplayLocationBuilder[-Query <: PipelineQuery](
- location: ShowAlertDisplayLocation)
- extends BaseShowAlertDisplayLocationBuilder[Query] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): ShowAlertDisplayLocation = location
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala
deleted file mode 100644
index 4c5dcf2a0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertIconDisplayInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticShowAlertIconDisplayInfoBuilder[-Query <: PipelineQuery](
- iconDisplayInfo: ShowAlertIconDisplayInfo)
- extends BaseShowAlertIconDisplayInfoBuilder[Query] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): Option[ShowAlertIconDisplayInfo] = Some(iconDisplayInfo)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala
deleted file mode 100644
index 87d611183..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.article
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.article.ArticleCandidateUrtItemBuilder.ArticleClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.BaseArticleCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleSeedType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object ArticleCandidateUrtItemBuilder {
- val ArticleClientEventInfoElement: String = "article"
-}
-
-case class ArticleCandidateUrtItemBuilder[
- -Query <: PipelineQuery,
- Candidate <: BaseArticleCandidate
-](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate],
- articleSeedType: ArticleSeedType = FollowingListSeed,
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, Candidate]
- ] = None,
- displayType: Option[ArticleDisplayType] = None,
- socialContextBuilder: Option[BaseSocialContextBuilder[Query, Candidate]] = None,
-) extends CandidateUrtEntryBuilder[Query, Candidate, ArticleItem] {
-
- override def apply(
- query: Query,
- articleCandidate: Candidate,
- candidateFeatures: FeatureMap
- ): ArticleItem = ArticleItem(
- id = articleCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- articleCandidate,
- candidateFeatures,
- Some(ArticleClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, articleCandidate, candidateFeatures)),
- displayType = displayType,
- socialContext =
- socialContextBuilder.flatMap(_.apply(query, articleCandidate, candidateFeatures)),
- articleSeedType = articleSeedType
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala
deleted file mode 100644
index 1d1f7c90a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.audio_space
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.audio_space.AudioSpaceCandidateUrtItemBuilder.AudioSpaceClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.AudioSpaceCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object AudioSpaceCandidateUrtItemBuilder {
- val AudioSpaceClientEventInfoElement: String = "audiospace"
-}
-
-case class AudioSpaceCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UniversalNoun[Any]],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, UniversalNoun[Any]]
- ] = None)
- extends CandidateUrtEntryBuilder[Query, AudioSpaceCandidate, AudioSpaceItem] {
-
- override def apply(
- query: Query,
- audioSpaceCandidate: AudioSpaceCandidate,
- candidateFeatures: FeatureMap
- ): AudioSpaceItem = AudioSpaceItem(
- id = audioSpaceCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- audioSpaceCandidate,
- candidateFeatures,
- Some(AudioSpaceClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, audioSpaceCandidate, candidateFeatures))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala
deleted file mode 100644
index e935df9dd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.card
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.card.CardCandidateUtrItemBuilder.CardClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.CardCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object CardCandidateUtrItemBuilder {
- val CardClientEventInfoElement: String = "card"
-}
-
-case class CardCandidateUtrItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CardCandidate],
- cardUrlBuilder: BaseStr[Query, CardCandidate],
- textBuilder: Option[BaseStr[Query, CardCandidate]],
- subtextBuilder: Option[BaseStr[Query, CardCandidate]],
- urlBuilder: Option[BaseUrlBuilder[Query, CardCandidate]],
- cardDisplayType: Option[CardDisplayType],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, CardCandidate],
- ] = None)
- extends CandidateUrtEntryBuilder[Query, CardCandidate, CardItem] {
-
- override def apply(
- query: Query,
- cardCandidate: CardCandidate,
- candidateFeatures: FeatureMap
- ): CardItem = CardItem(
- id = cardCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- cardCandidate,
- candidateFeatures,
- Some(CardClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, cardCandidate, candidateFeatures)),
- cardUrl = cardUrlBuilder(query, cardCandidate, candidateFeatures),
- text = textBuilder.map(_.apply(query, cardCandidate, candidateFeatures)),
- subtext = textBuilder.map(_.apply(query, cardCandidate, candidateFeatures)),
- url = urlBuilder.map(_.apply(query, cardCandidate, candidateFeatures)),
- displayType = cardDisplayType
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala
deleted file mode 100644
index a56385a7d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce.CommerceProductCandidateUrtItemBuilder.CommerceProductClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.CommerceProductCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object CommerceProductCandidateUrtItemBuilder {
- val CommerceProductClientEventInfoElement: String = "commerce-product"
-}
-
-case class CommerceProductCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CommerceProductCandidate],
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, CommerceProductCandidate]])
- extends CandidateUrtEntryBuilder[
- Query,
- CommerceProductCandidate,
- CommerceProductItem
- ] {
-
- override def apply(
- query: Query,
- candidate: CommerceProductCandidate,
- candidateFeatures: FeatureMap
- ): CommerceProductItem =
- CommerceProductItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = clientEventInfoBuilder(
- query,
- candidate,
- candidateFeatures,
- Some(CommerceProductClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala
deleted file mode 100644
index a48049314..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce.CommerceProductGroupCandidateUrtItemBuilder.CommerceProductGroupClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.CommerceProductGroupCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object CommerceProductGroupCandidateUrtItemBuilder {
- val CommerceProductGroupClientEventInfoElement: String = "commerce-product-group"
-}
-
-case class CommerceProductGroupCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CommerceProductGroupCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, CommerceProductGroupCandidate]
- ]) extends CandidateUrtEntryBuilder[
- Query,
- CommerceProductGroupCandidate,
- CommerceProductGroupItem
- ] {
-
- override def apply(
- query: Query,
- candidate: CommerceProductGroupCandidate,
- candidateFeatures: FeatureMap
- ): CommerceProductGroupItem =
- CommerceProductGroupItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = clientEventInfoBuilder(
- query,
- candidate,
- candidateFeatures,
- Some(CommerceProductGroupClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala
deleted file mode 100644
index 27d7f1e19..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary.EventCandidateUrtItemBuilder.EventClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventDisplayType
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventImage
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventTimeString
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventTitleFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventUrl
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedEventCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object EventCandidateUrtItemBuilder {
- val EventClientEventInfoElement = "event"
-}
-
-case class EventCandidateUrtItemBuilder[Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UnifiedEventCandidate],
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, UnifiedEventCandidate]] =
- None)
- extends CandidateUrtEntryBuilder[Query, UnifiedEventCandidate, TimelineItem] {
-
- override def apply(
- query: Query,
- candidate: UnifiedEventCandidate,
- candidateFeatures: FeatureMap
- ): TimelineItem = {
- EventSummaryItem(
- id = candidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query = query,
- candidate = candidate,
- candidateFeatures = candidateFeatures,
- element = Some(EventClientEventInfoElement)
- ),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)),
- title = candidateFeatures.get(EventTitleFeature),
- displayType = candidateFeatures.get(EventDisplayType),
- url = candidateFeatures.get(EventUrl),
- image = candidateFeatures.getOrElse(EventImage, None),
- timeString = candidateFeatures.getOrElse(EventTimeString, None)
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala
deleted file mode 100644
index 8cdbb065d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary.GenericSummaryActionBuilder.GenericSummaryActionClientEventInfoElement
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryAction
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object GenericSummaryActionBuilder {
- val GenericSummaryActionClientEventInfoElement: String = "genericsummary-action"
-}
-
-case class GenericSummaryActionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- urlBuilder: BaseUrlBuilder[Query, Candidate],
- clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, Candidate]] = None) {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): GenericSummaryAction = GenericSummaryAction(
- url = urlBuilder.apply(query, candidate, candidateFeatures),
- clientEventInfo = clientEventInfoBuilder.flatMap(
- _.apply(
- query,
- candidate,
- candidateFeatures,
- Some(GenericSummaryActionClientEventInfoElement)))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala
deleted file mode 100644
index 759dd48c2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary.GenericSummaryCandidateUrtItemBuilder.GenericSummaryClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.GenericSummaryCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItemDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.util.Time
-
-object GenericSummaryCandidateUrtItemBuilder {
- val GenericSummaryClientEventInfoElement: String = "genericsummary"
-}
-
-case class GenericSummaryCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, GenericSummaryCandidate],
- headlineRichTextBuilder: BaseRichTextBuilder[Query, GenericSummaryCandidate],
- displayType: GenericSummaryItemDisplayType,
- genericSummaryContextCandidateUrtItemBuilder: Option[
- GenericSummaryContextBuilder[Query, GenericSummaryCandidate]
- ] = None,
- genericSummaryActionCandidateUrtItemBuilder: Option[
- GenericSummaryActionBuilder[Query, GenericSummaryCandidate]
- ] = None,
- timestamp: Option[Time] = None,
- userAttributionIds: Option[Seq[Long]] = None,
- media: Option[Media] = None,
- promotedMetadata: Option[PromotedMetadata] = None,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, GenericSummaryCandidate]] =
- None)
- extends CandidateUrtEntryBuilder[Query, GenericSummaryCandidate, GenericSummaryItem] {
-
- override def apply(
- query: Query,
- genericSummaryCandidate: GenericSummaryCandidate,
- candidateFeatures: FeatureMap
- ): GenericSummaryItem = GenericSummaryItem(
- id = genericSummaryCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- genericSummaryCandidate,
- candidateFeatures,
- Some(GenericSummaryClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, genericSummaryCandidate, candidateFeatures)),
- headline = headlineRichTextBuilder.apply(query, genericSummaryCandidate, candidateFeatures),
- displayType = displayType,
- userAttributionIds = userAttributionIds.getOrElse(Seq.empty),
- media = media,
- context = genericSummaryContextCandidateUrtItemBuilder.map(
- _.apply(query, genericSummaryCandidate, candidateFeatures)),
- timestamp = timestamp,
- onClickAction = genericSummaryActionCandidateUrtItemBuilder.map(
- _.apply(query, genericSummaryCandidate, candidateFeatures)),
- promotedMetadata = promotedMetadata
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala
deleted file mode 100644
index e78476280..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryContext
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class GenericSummaryContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- richTextBuilder: BaseRichTextBuilder[Query, Candidate],
- icon: Option[HorizonIcon] = None) {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): GenericSummaryContext = GenericSummaryContext(
- richTextBuilder.apply(query, candidate, candidateFeatures),
- icon
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala
deleted file mode 100644
index 698b64f3b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.icon_label
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.icon_label.IconLabelCandidateUrtItemBuilder.IconLabelClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.LabelCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object IconLabelCandidateUrtItemBuilder {
- val IconLabelClientEventInfoElement: String = "iconlabel"
-}
-
-case class IconLabelCandidateUrtItemBuilder[-Query <: PipelineQuery, Candidate <: LabelCandidate](
- richTextBuilder: BaseRichTextBuilder[Query, Candidate],
- icon: Option[HorizonIcon] = None,
- entities: Option[List[RichTextEntity]] = None,
- clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, Candidate]] = None,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, Candidate]] = None)
- extends CandidateUrtEntryBuilder[Query, Candidate, IconLabelItem] {
-
- override def apply(
- query: Query,
- labelCandidate: Candidate,
- candidateFeatures: FeatureMap
- ): IconLabelItem =
- IconLabelItem(
- id = labelCandidate.id.toString,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder.flatMap(
- _.apply(query, labelCandidate, candidateFeatures, Some(IconLabelClientEventInfoElement))),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, labelCandidate, candidateFeatures)),
- text = richTextBuilder(query, labelCandidate, candidateFeatures),
- icon = icon,
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala
deleted file mode 100644
index 8f3d7826b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.message.CompactPromptCandidateUrtItemStringCenterBuilder.CompactPromptClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.CompactPromptCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object CompactPromptCandidateUrtItemStringCenterBuilder {
- val CompactPromptClientEventInfoElement: String = "message"
-}
-
-case class CompactPromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CompactPromptCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, CompactPromptCandidate]
- ] = None,
- headerTextBuilder: BaseStr[Query, CompactPromptCandidate],
- bodyTextBuilder: Option[BaseStr[Query, CompactPromptCandidate]] = None,
- headerRichTextBuilder: Option[BaseRichTextBuilder[Query, CompactPromptCandidate]] = None,
- bodyRichTextBuilder: Option[BaseRichTextBuilder[Query, CompactPromptCandidate]] = None)
- extends CandidateUrtEntryBuilder[Query, CompactPromptCandidate, MessagePromptItem] {
-
- override def apply(
- query: Query,
- compactPromptCandidate: CompactPromptCandidate,
- candidateFeatures: FeatureMap
- ): MessagePromptItem =
- MessagePromptItem(
- id = compactPromptCandidate.id.toString,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- compactPromptCandidate,
- candidateFeatures,
- Some(CompactPromptClientEventInfoElement)),
- feedbackActionInfo = feedbackActionInfoBuilder.flatMap(
- _.apply(query, compactPromptCandidate, candidateFeatures)),
- isPinned = None,
- content = CompactPromptMessageContent(
- headerText = headerTextBuilder.apply(query, compactPromptCandidate, candidateFeatures),
- bodyText = bodyTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures)),
- primaryButtonAction = None,
- secondaryButtonAction = None,
- action = None,
- headerRichText =
- headerRichTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures)),
- bodyRichText =
- bodyRichTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures))
- ),
- impressionCallbacks = None
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala
deleted file mode 100644
index 0ebee8e8c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.message.InlinePromptCandidateUrtItemStringCenterBuilder.InlinePromptClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.InlinePromptCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object InlinePromptCandidateUrtItemStringCenterBuilder {
- val InlinePromptClientEventInfoElement: String = "message"
-}
-
-case class InlinePromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, InlinePromptCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, InlinePromptCandidate]
- ] = None,
- headerTextBuilder: BaseStr[Query, InlinePromptCandidate],
- bodyTextBuilder: Option[BaseStr[Query, InlinePromptCandidate]] = None,
- headerRichTextBuilder: Option[BaseRichTextBuilder[Query, InlinePromptCandidate]] = None,
- bodyRichTextBuilder: Option[BaseRichTextBuilder[Query, InlinePromptCandidate]] = None,
- primaryMessageTextActionBuilder: Option[
- MessageTextActionBuilder[Query, InlinePromptCandidate]
- ] = None,
- secondaryMessageTextActionBuilder: Option[
- MessageTextActionBuilder[Query, InlinePromptCandidate]
- ] = None,
- socialContextBuilder: Option[BaseSocialContextBuilder[Query, InlinePromptCandidate]] = None,
- userFacePileBuilder: Option[
- UserFacePileBuilder
- ] = None)
- extends CandidateUrtEntryBuilder[Query, InlinePromptCandidate, MessagePromptItem] {
-
- override def apply(
- query: Query,
- inlinePromptCandidate: InlinePromptCandidate,
- candidateFeatures: FeatureMap
- ): MessagePromptItem =
- MessagePromptItem(
- id = inlinePromptCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- inlinePromptCandidate,
- candidateFeatures,
- Some(InlinePromptClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, inlinePromptCandidate, candidateFeatures)),
- isPinned = None,
- content = InlinePromptMessageContent(
- headerText = headerTextBuilder.apply(query, inlinePromptCandidate, candidateFeatures),
- bodyText = bodyTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)),
- primaryButtonAction = primaryMessageTextActionBuilder.map(
- _.apply(query, inlinePromptCandidate, candidateFeatures)),
- secondaryButtonAction = secondaryMessageTextActionBuilder.map(
- _.apply(query, inlinePromptCandidate, candidateFeatures)),
- headerRichText =
- headerRichTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)),
- bodyRichText =
- bodyRichTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)),
- socialContext =
- socialContextBuilder.flatMap(_.apply(query, inlinePromptCandidate, candidateFeatures)),
- userFacepile = userFacePileBuilder.map(_.apply())
- ),
- impressionCallbacks = None
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala
deleted file mode 100644
index 2871ac682..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object MessageTextActionBuilder {
- val MessageTextActionClientEventInfoElement: String = "message-text-action"
-}
-
-case class MessageTextActionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- textBuilder: BaseStr[Query, Candidate],
- dismissOnClick: Boolean,
- url: Option[String] = None,
- clientEventInfo: Option[ClientEventInfo] = None,
- onClickCallbacks: Option[List[Callback]] = None) {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): MessageTextAction = MessageTextAction(
- text = textBuilder(query, candidate, candidateFeatures),
- action = MessageAction(
- dismissOnClick,
- url,
- clientEventInfo,
- onClickCallbacks
- )
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala
deleted file mode 100644
index ce87e64cb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepileDisplayType
-
-case class UserFacePileBuilder(
- userIds: Seq[Long],
- featuredUserIds: Seq[Long],
- action: Option[MessageTextAction],
- actionType: Option[MessageActionType],
- displaysFeaturingText: Option[Boolean],
- displayType: Option[UserFacepileDisplayType]) {
-
- def apply(): UserFacepile = UserFacepile(
- userIds = userIds,
- featuredUserIds = featuredUserIds,
- action = action,
- actionType = actionType,
- displaysFeaturingText = displaysFeaturingText,
- displayType = displayType
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala
deleted file mode 100644
index 5d916f424..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.moment
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.moment.MomentAnnotationCandidateUrtItemBuilder.MomentAnnotationItemClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.MomentAnnotationCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object MomentAnnotationCandidateUrtItemBuilder {
- val MomentAnnotationItemClientEventInfoElement = "metadata"
-}
-
-case class MomentAnnotationCandidateUrtItemBuilder[Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, MomentAnnotationCandidate],
- annotationTextRichTextBuilder: BaseRichTextBuilder[Query, MomentAnnotationCandidate],
- annotationHeaderRichTextBuilder: BaseRichTextBuilder[Query, MomentAnnotationCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, MomentAnnotationCandidate]
- ] = None,
-) extends CandidateUrtEntryBuilder[Query, MomentAnnotationCandidate, MomentAnnotationItem] {
-
- override def apply(
- query: Query,
- candidate: MomentAnnotationCandidate,
- candidateFeatures: FeatureMap
- ): MomentAnnotationItem = MomentAnnotationItem(
- id = candidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- candidate,
- candidateFeatures,
- Some(MomentAnnotationItemClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)),
- isPinned = None,
- text =
- candidate.text.map(_ => annotationTextRichTextBuilder(query, candidate, candidateFeatures)),
- header = candidate.header.map(_ =>
- annotationHeaderRichTextBuilder(query, candidate, candidateFeatures)),
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala
deleted file mode 100644
index 7ab7308b2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.relevance_prompt
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.relevance_prompt.RelevancePromptCandidateUrtItemStringCenterBuilder.RelevancePromptClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptFollowUpFeedbackType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object RelevancePromptCandidateUrtItemStringCenterBuilder {
- val RelevancePromptClientEventInfoElement: String = "relevance_prompt"
-}
-
-case class RelevancePromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, RelevancePromptCandidate],
- titleTextBuilder: BaseStr[Query, RelevancePromptCandidate],
- confirmationTextBuilder: BaseStr[Query, RelevancePromptCandidate],
- isRelevantTextBuilder: BaseStr[Query, RelevancePromptCandidate],
- notRelevantTextBuilder: BaseStr[Query, RelevancePromptCandidate],
- displayType: RelevancePromptDisplayType,
- isRelevantCallback: Callback,
- notRelevantCallback: Callback,
- isRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType] = None,
- notRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType] = None,
- impressionCallbacks: Option[List[Callback]] = None)
- extends CandidateUrtEntryBuilder[Query, RelevancePromptCandidate, PromptItem] {
-
- override def apply(
- query: Query,
- relevancePromptCandidate: RelevancePromptCandidate,
- candidateFeatures: FeatureMap
- ): PromptItem =
- PromptItem(
- id = relevancePromptCandidate.id,
- sortIndex = None,
- clientEventInfo = clientEventInfoBuilder(
- query,
- relevancePromptCandidate,
- candidateFeatures,
- Some(RelevancePromptClientEventInfoElement)),
- feedbackActionInfo = None,
- content = RelevancePromptContent(
- title = titleTextBuilder(query, relevancePromptCandidate, candidateFeatures),
- confirmation = confirmationTextBuilder(query, relevancePromptCandidate, candidateFeatures),
- isRelevantText = isRelevantTextBuilder(query, relevancePromptCandidate, candidateFeatures),
- notRelevantText =
- notRelevantTextBuilder(query, relevancePromptCandidate, candidateFeatures),
- isRelevantCallback = isRelevantCallback,
- notRelevantCallback = notRelevantCallback,
- displayType = displayType,
- isRelevantFollowUp = isRelevantFollowUp,
- notRelevantFollowUp = notRelevantFollowUp,
- ),
- impressionCallbacks = impressionCallbacks
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala
deleted file mode 100644
index ce0beeb9e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.suggestion
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.suggestion.SpellingSuggestionCandidateUrtItemBuilder.SpellingItemClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.suggestion.SpellingSuggestionCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object SpellingSuggestionCandidateUrtItemBuilder {
- val SpellingItemClientEventInfoElement: String = "spelling"
-}
-
-case class SpellingSuggestionCandidateUrtItemBuilder[Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, SpellingSuggestionCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, SpellingSuggestionCandidate]
- ] = None,
-) extends CandidateUrtEntryBuilder[Query, SpellingSuggestionCandidate, SpellingItem] {
-
- override def apply(
- query: Query,
- candidate: SpellingSuggestionCandidate,
- candidateFeatures: FeatureMap
- ): SpellingItem = SpellingItem(
- id = candidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- candidate,
- candidateFeatures,
- Some(SpellingItemClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)),
- textResult = candidate.textResult,
- spellingActionType = candidate.spellingActionType,
- originalQuery = candidate.originalQuery
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala
deleted file mode 100644
index 4c449637f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.tile
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tile.TileCandidateUrtItemBuilder.TopicTileClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object TileCandidateUrtItemBuilder {
- val TopicTileClientEventInfoElement: String = "tile"
-}
-
-case class TileCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, PromptCarouselTileCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, PromptCarouselTileCandidate]
- ] = None)
- extends CandidateUrtEntryBuilder[Query, PromptCarouselTileCandidate, TileItem] {
-
- override def apply(
- query: Query,
- tileCandidate: PromptCarouselTileCandidate,
- candidateFeatures: FeatureMap
- ): TileItem = TileItem(
- id = tileCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- tileCandidate,
- candidateFeatures,
- Some(TopicTileClientEventInfoElement)),
- title = "", //This data is ignored do
- supportingText = "",
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, tileCandidate, candidateFeatures)),
- image = None,
- url = None,
- content = StandardTileContent(
- title = "",
- supportingText = "",
- badge = None
- )
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala
deleted file mode 100644
index 20253fea0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSEnumParam
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.NoIconTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillWithoutActionIconDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder
-
-object TopicCandidateDisplayType extends Enumeration {
- type TopicDisplayType = Value
-
- val Basic = Value
- val Pill = Value
- val NoIcon = Value
- val PillWithoutActionIcon = Value
-}
-
-case class ParamTopicDisplayTypeBuilder(
- displayTypeParam: FSEnumParam[TopicCandidateDisplayType.type])
- extends BaseTopicDisplayTypeBuilder[PipelineQuery, TopicCandidate] {
-
- override def apply(
- query: PipelineQuery,
- candidate: TopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[TopicDisplayType] = {
- val displayType = query.params(displayTypeParam)
- displayType match {
- case TopicCandidateDisplayType.Basic => Some(BasicTopicDisplayType)
- case TopicCandidateDisplayType.Pill => Some(PillTopicDisplayType)
- case TopicCandidateDisplayType.NoIcon =>
- Some(NoIconTopicDisplayType)
- case TopicCandidateDisplayType.PillWithoutActionIcon => Some(PillWithoutActionIconDisplayType)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala
deleted file mode 100644
index 78d941c19..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PivotTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.RecommendationTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder
-import com.twitter.timelines.configapi.FSEnumParam
-
-object TopicFunctionalityTypeParamValue extends Enumeration {
- type TopicFunctionalityType = Value
-
- val Basic = Value
- val Pivot = Value
- val Recommendation = Value
-}
-
-case class ParamTopicFunctionalityTypeBuilder(
- functionalityTypeParam: FSEnumParam[TopicFunctionalityTypeParamValue.type])
- extends BaseTopicFunctionalityTypeBuilder[PipelineQuery, TopicCandidate] {
-
- override def apply(
- query: PipelineQuery,
- candidate: TopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[TopicFunctionalityType] = {
- val functionalityType = query.params(functionalityTypeParam)
- functionalityType match {
- case TopicFunctionalityTypeParamValue.Basic => Some(BasicTopicFunctionalityType)
- case TopicFunctionalityTypeParamValue.Pivot => Some(PivotTopicFunctionalityType)
- case TopicFunctionalityTypeParamValue.Recommendation =>
- Some(RecommendationTopicFunctionalityType)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala
deleted file mode 100644
index fbe8c2783..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType
-
-case class StaticTopicDisplayTypeBuilder(
- displayType: TopicDisplayType)
- extends BaseTopicDisplayTypeBuilder[PipelineQuery, BaseTopicCandidate] {
-
- override def apply(
- query: PipelineQuery,
- candidate: BaseTopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[TopicDisplayType] = Some(displayType)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala
deleted file mode 100644
index 73e99d0a3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticTopicFunctionalityTypeBuilder(
- functionalityType: TopicFunctionalityType)
- extends BaseTopicFunctionalityTypeBuilder[PipelineQuery, BaseTopicCandidate] {
-
- override def apply(
- query: PipelineQuery,
- candidate: BaseTopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[TopicFunctionalityType] = Some(functionalityType)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala
deleted file mode 100644
index a049e08fd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic.TopicCandidateUrtItemBuilder.TopicClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object TopicCandidateUrtItemBuilder {
- val TopicClientEventInfoElement: String = "topic"
-}
-
-case class TopicCandidateUrtItemBuilder[-Query <: PipelineQuery, Candidate <: BaseTopicCandidate](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate],
- topicFunctionalityTypeBuilder: Option[BaseTopicFunctionalityTypeBuilder[Query, Candidate]] = None,
- topicDisplayTypeBuilder: Option[BaseTopicDisplayTypeBuilder[Query, Candidate]] = None,
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, Candidate]
- ] = None)
- extends CandidateUrtEntryBuilder[Query, Candidate, TopicItem] {
-
- override def apply(
- query: Query,
- topicCandidate: Candidate,
- candidateFeatures: FeatureMap
- ): TopicItem =
- TopicItem(
- id = topicCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- topicCandidate,
- candidateFeatures,
- Some(TopicClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)),
- topicFunctionalityType =
- topicFunctionalityTypeBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)),
- topicDisplayType =
- topicDisplayTypeBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala
deleted file mode 100644
index 40f436159..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic.TopicCandidateUrtItemBuilder.TopicClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTileStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class VerticalGridTopicCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, TopicCandidate],
- verticalGridItemTopicFunctionalityType: VerticalGridItemTopicFunctionalityType,
- verticalGridItemTileStyle: VerticalGridItemTileStyle,
- urlBuilder: Option[BaseUrlBuilder[Query, TopicCandidate]] = None,
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, TopicCandidate]
- ] = None)
- extends CandidateUrtEntryBuilder[Query, TopicCandidate, VerticalGridItem] {
-
- override def apply(
- query: Query,
- topicCandidate: TopicCandidate,
- candidateFeatures: FeatureMap
- ): VerticalGridItem = {
- VerticalGridItemTopicTile(
- id = topicCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- topicCandidate,
- candidateFeatures,
- Some(TopicClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)),
- style = Some(verticalGridItemTileStyle),
- functionalityType = Some(verticalGridItemTopicFunctionalityType),
- url = urlBuilder.map(_.apply(query, topicCandidate, candidateFeatures))
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala
deleted file mode 100644
index c3f5c45ad..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend.TrendCandidateUrtItemBuilder.TrendsClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendDescription
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendDomainContext
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendGroupedTrends
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendNormalizedTrendName
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTrendName
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTweetCount
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendUrl
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object TrendCandidateUrtItemBuilder {
- final val TrendsClientEventInfoElement = "trend"
-}
-
-case class TrendCandidateUrtItemBuilder[Query <: PipelineQuery](
- trendMetaDescriptionBuilder: TrendMetaDescriptionBuilder[Query, UnifiedTrendCandidate],
- promotedMetadataBuilder: BasePromotedMetadataBuilder[Query, UnifiedTrendCandidate],
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UnifiedTrendCandidate],
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, UnifiedTrendCandidate]] =
- None)
- extends CandidateUrtEntryBuilder[Query, UnifiedTrendCandidate, TimelineItem] {
-
- override def apply(
- query: Query,
- candidate: UnifiedTrendCandidate,
- candidateFeatures: FeatureMap
- ): TimelineItem = {
- TrendItem(
- id = candidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query = query,
- candidate = candidate,
- candidateFeatures = candidateFeatures,
- element = Some(TrendsClientEventInfoElement)
- ),
- feedbackActionInfo = None,
- normalizedTrendName = candidateFeatures.get(TrendNormalizedTrendName),
- trendName = candidateFeatures.get(TrendTrendName),
- url = candidateFeatures.get(TrendUrl),
- description = candidateFeatures.getOrElse(TrendDescription, None),
- metaDescription = trendMetaDescriptionBuilder(query, candidate, candidateFeatures),
- tweetCount = candidateFeatures.getOrElse(TrendTweetCount, None),
- domainContext = candidateFeatures.getOrElse(TrendDomainContext, None),
- promotedMetadata = promotedMetadataBuilder(
- query = query,
- candidate = candidate,
- candidateFeatures = candidateFeatures
- ),
- groupedTrends = candidateFeatures.getOrElse(TrendGroupedTrends, None)
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala
deleted file mode 100644
index b8cc639a0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.Str
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendAdvertiserNameFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTweetCount
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.trends.trending_content.util.CompactingNumberLocalizer
-
-case class TrendMetaDescriptionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- promotedByMetaDescriptionStr: Str[PipelineQuery, UniversalNoun[Any]],
- tweetCountMetaDescriptionStr: Str[PipelineQuery, UniversalNoun[Any]],
- compactingNumberLocalizer: CompactingNumberLocalizer) {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[String] = {
- val promotedMetaDescription =
- candidateFeatures.getOrElse(PromotedTrendAdvertiserNameFeature, None).map { advertiserName =>
- promotedByMetaDescriptionStr(query, candidate, candidateFeatures).format(advertiserName)
- }
-
- val organicMetaDescription = candidateFeatures.getOrElse(TrendTweetCount, None).map {
- tweetCount =>
- val compactedTweetCount = compactingNumberLocalizer.localizeAndCompact(
- query.getLanguageCode
- .getOrElse("en"),
- tweetCount)
- tweetCountMetaDescriptionStr(query, candidate, candidateFeatures).format(
- compactedTweetCount)
- }
-
- promotedMetaDescription.orElse(organicMetaDescription)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala
deleted file mode 100644
index 9c1c34fa5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend
-
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendDescriptionFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendDisclosureTypeFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendIdFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendImpressionIdFeature
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendNameFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object TrendPromotedMetadataBuilder
- extends BasePromotedMetadataBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): Option[PromotedMetadata] = {
- // If a promoted trend name exists, then this is a promoted trend
- candidateFeatures.getOrElse(PromotedTrendNameFeature, None).map { promotedTrendName =>
- PromotedMetadata(
- // This is the current product behavior that advertiserId is always set to 0L.
- // Correct advertiser name comes from Trend's trendMetadata.metaDescription.
- advertiserId = 0L,
- disclosureType = candidateFeatures.getOrElse(PromotedTrendDisclosureTypeFeature, None),
- experimentValues = None,
- promotedTrendId = candidateFeatures.getOrElse(PromotedTrendIdFeature, None),
- promotedTrendName = Some(promotedTrendName),
- promotedTrendQueryTerm = None,
- adMetadataContainer = None,
- promotedTrendDescription =
- candidateFeatures.getOrElse(PromotedTrendDescriptionFeature, None),
- impressionString = candidateFeatures.getOrElse(PromotedTrendImpressionIdFeature, None),
- clickTrackingInfo = None
- )
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala
deleted file mode 100644
index d02b96f1c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref.ContextualTweetRefBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder.TweetClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.IsPinnedFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseEntryIdToReplaceBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseTimelinesScoreInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseTweetHighlightsBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case object TweetCandidateUrtItemBuilder {
- val TweetClientEventInfoElement = "tweet"
-}
-
-case class TweetCandidateUrtItemBuilder[Query <: PipelineQuery, Candidate <: BaseTweetCandidate](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate],
- displayType: TweetDisplayType = Tweet,
- entryIdToReplaceBuilder: Option[BaseEntryIdToReplaceBuilder[Query, Candidate]] = None,
- socialContextBuilder: Option[BaseSocialContextBuilder[Query, Candidate]] = None,
- highlightsBuilder: Option[BaseTweetHighlightsBuilder[Query, Candidate]] = None,
- innerTombstoneInfo: Option[TombstoneInfo] = None,
- timelinesScoreInfoBuilder: Option[BaseTimelinesScoreInfoBuilder[Query, Candidate]] = None,
- hasModeratedReplies: Option[Boolean] = None,
- forwardPivot: Option[ForwardPivot] = None,
- innerForwardPivot: Option[ForwardPivot] = None,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, Candidate]] = None,
- promotedMetadata: Option[PromotedMetadata] = None,
- conversationAnnotation: Option[ConversationAnnotation] = None,
- contextualTweetRefBuilder: Option[ContextualTweetRefBuilder[Candidate]] = None,
- prerollMetadata: Option[PrerollMetadata] = None,
- replyBadge: Option[Badge] = None,
- destinationBuilder: Option[BaseUrlBuilder[Query, Candidate]] = None)
- extends CandidateUrtEntryBuilder[Query, Candidate, TweetItem] {
-
- override def apply(
- pipelineQuery: Query,
- tweetCandidate: Candidate,
- candidateFeatures: FeatureMap
- ): TweetItem = {
- val isPinned = candidateFeatures.getTry(IsPinnedFeature).toOption
-
- TweetItem(
- id = tweetCandidate.id,
- entryNamespace = TweetItem.TweetEntryNamespace,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- pipelineQuery,
- tweetCandidate,
- candidateFeatures,
- Some(TweetClientEventInfoElement)),
- feedbackActionInfo = feedbackActionInfoBuilder.flatMap(
- _.apply(pipelineQuery, tweetCandidate, candidateFeatures)),
- isPinned = isPinned,
- entryIdToReplace =
- entryIdToReplaceBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)),
- socialContext =
- socialContextBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)),
- highlights =
- highlightsBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)),
- displayType = displayType,
- innerTombstoneInfo = innerTombstoneInfo,
- timelinesScoreInfo = timelinesScoreInfoBuilder
- .flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)),
- hasModeratedReplies = hasModeratedReplies,
- forwardPivot = forwardPivot,
- innerForwardPivot = innerForwardPivot,
- promotedMetadata = promotedMetadata,
- conversationAnnotation = conversationAnnotation,
- contextualTweetRef = contextualTweetRefBuilder.flatMap(_.apply(tweetCandidate)),
- prerollMetadata = prerollMetadata,
- replyBadge = replyBadge,
- destination =
- destinationBuilder.map(_.apply(pipelineQuery, tweetCandidate, candidateFeatures))
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala
deleted file mode 100644
index 41ed4ed71..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.twitter_list
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.twitter_list.TwitterListCandidateUrtItemBuilder.ListClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object TwitterListCandidateUrtItemBuilder {
- val ListClientEventInfoElement: String = "list"
-}
-
-case class TwitterListCandidateUrtItemBuilder[-Query <: PipelineQuery](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, TwitterListCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, TwitterListCandidate]
- ] = None,
- displayType: Option[TwitterListDisplayType] = None)
- extends CandidateUrtEntryBuilder[Query, TwitterListCandidate, TwitterListItem] {
-
- override def apply(
- query: Query,
- twitterListCandidate: TwitterListCandidate,
- candidateFeatures: FeatureMap
- ): TwitterListItem = TwitterListItem(
- id = twitterListCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- twitterListCandidate,
- candidateFeatures,
- Some(ListClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, twitterListCandidate, candidateFeatures)),
- displayType = displayType
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala
deleted file mode 100644
index c4b67ce04..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.unified_trend_event
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary.EventCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend.TrendCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedEventCandidate
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendCandidate
-import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendEventCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class UnifiedTrendEventCandidateUrtItemBuilder[Query <: PipelineQuery](
- eventCandidateUrtItemBuilder: EventCandidateUrtItemBuilder[Query],
- trendCandidateUrtItemBuilder: TrendCandidateUrtItemBuilder[Query])
- extends CandidateUrtEntryBuilder[Query, UnifiedTrendEventCandidate[Any], TimelineItem] {
-
- override def apply(
- query: Query,
- candidate: UnifiedTrendEventCandidate[Any],
- candidateFeatures: FeatureMap
- ): TimelineItem = {
- candidate match {
- case event: UnifiedEventCandidate =>
- eventCandidateUrtItemBuilder(
- query = query,
- candidate = event,
- candidateFeatures = candidateFeatures)
- case trend: UnifiedTrendCandidate =>
- trendCandidateUrtItemBuilder(
- query = query,
- candidate = trend,
- candidateFeatures = candidateFeatures)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala
deleted file mode 100644
index 95a7e6bd9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.item.user
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder.UserClientEventInfoElement
-import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate
-import com.twitter.product_mixer.component_library.model.candidate.IsMarkUnreadFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.user.BaseUserReactiveTriggersBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UserCandidateUrtItemBuilder {
- val UserClientEventInfoElement: String = "user"
-}
-
-case class UserCandidateUrtItemBuilder[Query <: PipelineQuery, UserCandidate <: BaseUserCandidate](
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, UserCandidate]
- ] = None,
- displayType: UserDisplayType = User,
- promotedMetadataBuilder: Option[BasePromotedMetadataBuilder[Query, UserCandidate]] = None,
- socialContextBuilder: Option[BaseSocialContextBuilder[Query, UserCandidate]] = None,
- reactiveTriggersBuilder: Option[BaseUserReactiveTriggersBuilder[Query, UserCandidate]] = None,
- enableReactiveBlending: Option[Boolean] = None)
- extends CandidateUrtEntryBuilder[Query, UserCandidate, UserItem] {
-
- override def apply(
- query: Query,
- userCandidate: UserCandidate,
- candidateFeatures: FeatureMap
- ): UserItem = {
- val isMarkUnread = candidateFeatures.getTry(IsMarkUnreadFeature).toOption
-
- UserItem(
- id = userCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- clientEventInfo = clientEventInfoBuilder(
- query,
- userCandidate,
- candidateFeatures,
- Some(UserClientEventInfoElement)),
- feedbackActionInfo =
- feedbackActionInfoBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)),
- isMarkUnread = isMarkUnread,
- displayType = displayType,
- promotedMetadata =
- promotedMetadataBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)),
- socialContext =
- socialContextBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)),
- reactiveTriggers =
- reactiveTriggersBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)),
- enableReactiveBlending = enableReactiveBlending
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala
deleted file mode 100644
index 0c0eca37b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder
-
-/**
- * Sets the [[ClientEventInfo]] with the `component` field set to [[component]]
- * @see [[http://go/client-events]]
- */
-case class ClientEventInfoBuilder[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- component: String,
- detailsBuilder: Option[BaseClientEventDetailsBuilder[Query, Candidate]] = None)
- extends BaseClientEventInfoBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap,
- element: Option[String]
- ): Option[ClientEventInfo] =
- Some(
- ClientEventInfo(
- component = Some(component),
- element = element,
- details = detailsBuilder.flatMap(_.apply(query, candidate, candidateFeatures)),
- action = None,
- entityToken = None)
- )
-}
-
-/**
- * In rare cases you might not want to send client event info. For
- * example, this might be set already on the client for some legacy
- * timelines.
- */
-object EmptyClientEventInfoBuilder
- extends BaseClientEventInfoBuilder[PipelineQuery, UniversalNoun[Any]] {
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap,
- element: Option[String]
- ): Option[ClientEventInfo] = None
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala
deleted file mode 100644
index ad8034dbc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.bijection.scrooge.BinaryScalaCodec
-import com.twitter.bijection.Base64String
-import com.twitter.bijection.{Injection => Serializer}
-import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ConversationTweetClientEventDetailsBuilder.ControllerDataSerializer
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.suggests.controller_data.home_tweets.thriftscala.HomeTweetsControllerData
-import com.twitter.suggests.controller_data.thriftscala.ControllerData
-import com.twitter.suggests.controller_data.home_tweets.v1.thriftscala.{
- HomeTweetsControllerData => HomeTweetsControllerDataV1
-}
-import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2}
-
-object ConversationTweetClientEventDetailsBuilder {
- implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] =
- BinaryScalaCodec(ControllerData)
-
- val ControllerDataSerializer: Serializer[ControllerData, String] =
- Serializer.connect[ControllerData, Array[Byte], Base64String, String]
-}
-
-case class ConversationTweetClientEventDetailsBuilder[-Query <: PipelineQuery](
- injectionType: Option[String])
- extends BaseClientEventDetailsBuilder[Query, BaseTweetCandidate] {
-
- override def apply(
- query: Query,
- tweetCandidate: BaseTweetCandidate,
- candidateFeatures: FeatureMap
- ): Option[ClientEventDetails] =
- Some(
- ClientEventDetails(
- conversationDetails = None,
- timelinesDetails = Some(
- TimelinesDetails(
- injectionType = injectionType,
- controllerData = Some(buildControllerData(query.getUserOrGuestId)),
- sourceData = None)),
- articleDetails = None,
- liveEventDetails = None,
- commerceDetails = None
- ))
-
- private def buildControllerData(traceId: Option[Long]): String =
- ControllerDataSerializer(
- ControllerData.V2(
- ControllerDataV2.HomeTweets(
- HomeTweetsControllerData.V1(
- HomeTweetsControllerDataV1(
- tweetTypesBitmap = 0L,
- traceId = traceId,
- )
- )
- )
- )
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala
deleted file mode 100644
index 7db66990f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticUrlBuilder(url: String, urlType: UrlType)
- extends BaseUrlBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): Url = Url(url = url, urlType = urlType)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala
deleted file mode 100644
index af28b49f3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.bijection.scrooge.BinaryScalaCodec
-import com.twitter.bijection.Base64String
-import com.twitter.bijection.{Injection => Serializer}
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder
-import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.suggests.controller_data.thriftscala.ControllerData
-import com.twitter.suggests.controller_data.timelines_topic.thriftscala.TimelinesTopicControllerData
-import com.twitter.suggests.controller_data.timelines_topic.v1.thriftscala.{
- TimelinesTopicControllerData => TimelinesTopicControllerDataV1
-}
-import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2}
-
-object TopicClientEventDetailsBuilder {
- implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] =
- BinaryScalaCodec(ControllerData)
-
- val ControllerDataSerializer: Serializer[ControllerData, String] =
- Serializer.connect[ControllerData, Array[Byte], Base64String, String]
-}
-
-case class TopicClientEventDetailsBuilder[-Query <: PipelineQuery]()
- extends BaseClientEventDetailsBuilder[Query, BaseTopicCandidate] {
-
- import TopicClientEventDetailsBuilder._
-
- override def apply(
- query: Query,
- topicCandidate: BaseTopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[ClientEventDetails] =
- Some(
- ClientEventDetails(
- conversationDetails = None,
- timelinesDetails = Some(
- TimelinesDetails(
- injectionType = None,
- controllerData = buildControllerData(topicCandidate.id),
- sourceData = None)),
- articleDetails = None,
- liveEventDetails = None,
- commerceDetails = None
- ))
-
- private def buildControllerData(topicId: Long): Option[String] =
- Some(
- ControllerData
- .V2(ControllerDataV2.TimelinesTopic(TimelinesTopicControllerData.V1(
- TimelinesTopicControllerDataV1(topicTypesBitmap = 0L, topicId = topicId)))))
- .map(ControllerDataSerializer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala
deleted file mode 100644
index cfb7cb5ff..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorMarkNotInterestedTopic
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class TopicNotInterestedFeedbackActionInfoBuilder[-Query <: PipelineQuery]()
- extends BaseFeedbackActionInfoBuilder[Query, BaseTopicCandidate] {
-
- override def apply(
- query: Query,
- topicCandidate: BaseTopicCandidate,
- candidateFeatures: FeatureMap
- ): Option[FeedbackActionInfo] = {
- Some(
- FeedbackActionInfo(
- feedbackActions = Seq(
- FeedbackAction(
- feedbackType = RichBehavior,
- richBehavior = Some(
- RichFeedbackBehaviorMarkNotInterestedTopic(topicCandidate.id.toString)
- ),
- hasUndoAction = Some(true),
- prompt = None,
- confirmation = None,
- feedbackUrl = None,
- clientEventInfo = None,
- childFeedbackActions = None,
- confirmationDisplayType = None,
- icon = None,
- subprompt = None,
- encodedFeedbackRequest = None
- )
- ),
- feedbackMetadata = None,
- displayContext = None,
- clientEventInfo = None
- ))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala
deleted file mode 100644
index 451b347ae..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.bijection.scrooge.BinaryScalaCodec
-import com.twitter.bijection.Base64String
-import com.twitter.bijection.{Injection => Serializer}
-import com.twitter.interests_mixer.model.request.{HasTopicId => InterestsMixerHasTopicId}
-import com.twitter.explore_mixer.model.request.{HasTopicId => ExploreMixerHasTopicId}
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.suggests.controller_data.home_tweets.thriftscala.HomeTweetsControllerData
-import com.twitter.suggests.controller_data.home_tweets.v1.thriftscala.{
- HomeTweetsControllerData => HomeTweetsControllerDataV1
-}
-import com.twitter.suggests.controller_data.thriftscala.ControllerData
-import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2}
-
-object TopicTweetClientEventDetailsBuilder {
- implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] =
- BinaryScalaCodec(ControllerData)
-
- val ControllerDataSerializer: Serializer[ControllerData, String] =
- Serializer.connect[ControllerData, Array[Byte], Base64String, String]
-}
-
-case class TopicTweetClientEventDetailsBuilder[-Query <: PipelineQuery]()
- extends BaseClientEventDetailsBuilder[Query, TweetCandidate] {
-
- import TopicTweetClientEventDetailsBuilder._
-
- override def apply(
- query: Query,
- topicTweetCandidate: TweetCandidate,
- candidateFeatures: FeatureMap
- ): Option[ClientEventDetails] =
- Some(
- ClientEventDetails(
- conversationDetails = None,
- timelinesDetails = Some(
- TimelinesDetails(
- injectionType = None,
- controllerData = buildControllerData(getTopicId(query)),
- sourceData = None)),
- articleDetails = None,
- liveEventDetails = None,
- commerceDetails = None
- ))
-
- private def getTopicId(query: Query): Option[Long] = {
- query match {
- case query: InterestsMixerHasTopicId => query.topicId
- case query: ExploreMixerHasTopicId => query.topicId
- case _ => None
- }
- }
-
- private def buildControllerData(topicId: Option[Long]): Option[String] =
- Some(
- ControllerData
- .V2(ControllerDataV2.HomeTweets(HomeTweetsControllerData.V1(
- HomeTweetsControllerDataV1(tweetTypesBitmap = 0L, topicId = topicId)))))
- .map(ControllerDataSerializer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala
deleted file mode 100644
index fa32e2127..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarouselMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-object TopicsToFollowModuleMetadataBuilder {
-
- val TopicsPerRow = 7
-
- /*
- * rows = min(MAX_NUM_ROWS, # topics / TOPICS_PER_ROW)
- * where TOPICS_PER_ROW = 7
- */
- def getCarouselRowCount(topicsCount: Int, maxCarouselRows: Int): Int =
- Math.min(maxCarouselRows, (topicsCount / TopicsPerRow) + 1)
-}
-
-case class TopicsToFollowModuleMetadataBuilder(maxCarouselRowsParam: Param[Int])
- extends BaseModuleMetadataBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- import TopicsToFollowModuleMetadataBuilder._
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleMetadata = {
- val rowCount = getCarouselRowCount(candidates.size, query.params(maxCarouselRowsParam))
- ModuleMetadata(
- adsMetadata = None,
- conversationMetadata = None,
- gridCarouselMetadata = Some(GridCarouselMetadata(numRows = Some(rowCount)))
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala
deleted file mode 100644
index 04d6fae7b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.Str
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.Frown
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SeeFewer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stringcenter.client.ExternalStringRegistry
-import com.twitter.stringcenter.client.StringCenter
-
-case class WhoToFollowFeedbackActionInfoBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]
-](
- externalStringRegistry: ExternalStringRegistry,
- stringCenter: StringCenter,
- encodedFeedbackRequest: Option[String])
- extends BaseFeedbackActionInfoBuilder[Query, Candidate] {
-
- private val seeLessOftenFeedback =
- externalStringRegistry.createProdString("Feedback.seeLessOften")
- private val seeLessOftenConfirmationFeedback =
- externalStringRegistry.createProdString("Feedback.seeLessOftenConfirmation")
-
- override def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[FeedbackActionInfo] = Some(
- FeedbackActionInfo(
- feedbackActions = Seq(
- FeedbackAction(
- feedbackType = SeeFewer,
- prompt = Some(
- Str(seeLessOftenFeedback, stringCenter, None)
- .apply(query, candidate, candidateFeatures)),
- confirmation = Some(
- Str(seeLessOftenConfirmationFeedback, stringCenter, None)
- .apply(query, candidate, candidateFeatures)),
- childFeedbackActions = None,
- feedbackUrl = None,
- confirmationDisplayType = None,
- clientEventInfo = None,
- richBehavior = None,
- subprompt = None,
- icon = Some(Frown), // ignored by unsupported clients
- hasUndoAction = Some(true),
- encodedFeedbackRequest = encodedFeedbackRequest
- )
- ),
- feedbackMetadata = None,
- displayContext = None,
- clientEventInfo = None
- )
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala
deleted file mode 100644
index 6cc1ad677..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.operation
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorDisplayTreatment
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class CursorCandidateUrtOperationBuilder[-Query <: PipelineQuery](
- cursorType: CursorType,
- displayTreatment: Option[CursorDisplayTreatment] = None,
- idToReplace: Option[Long] = None)
- extends CandidateUrtEntryBuilder[Query, CursorCandidate, CursorOperation] {
-
- override def apply(
- query: Query,
- cursorCandidate: CursorCandidate,
- candidateFeatures: FeatureMap
- ): CursorOperation = CursorOperation(
- id = cursorCandidate.id,
- sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase
- value = cursorCandidate.value,
- cursorType = cursorType,
- displayTreatment = displayTreatment,
- idToReplace = idToReplace
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala
deleted file mode 100644
index 6edc3b593..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.promoted
-
-import com.twitter.ads.adserver.{thriftscala => ads}
-import com.twitter.ads.common.base.{thriftscala => ac}
-import com.twitter.adserver.{thriftscala => ad}
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.util.AdMetadataContainerSerializer
-
-case class FeaturePromotedMetadataBuilder(adImpressionFeature: Feature[_, Option[ad.AdImpression]])
- extends BasePromotedMetadataBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): Option[PromotedMetadata] = {
- candidateFeatures.getOrElse(adImpressionFeature, None).map { impression =>
- PromotedMetadata(
- advertiserId = impression.advertiserId,
- disclosureType = impression.disclosureType.map(convertDisclosureType),
- experimentValues = impression.experimentValues.map(_.toMap),
- promotedTrendId = impression.promotedTrendId.map(_.toLong),
- promotedTrendName = impression.promotedTrendName,
- promotedTrendQueryTerm = impression.promotedTrendQueryTerm,
- adMetadataContainer =
- impression.serializedAdMetadataContainer.flatMap(convertAdMetadataContainer),
- promotedTrendDescription = impression.promotedTrendDescription,
- impressionString = impression.impressionString,
- clickTrackingInfo = impression.clickTrackingInfo.map(convertClickTrackingInfo),
- )
- }
- }
-
- private def convertAdMetadataContainer(
- serializedAdMetadataContainer: ac.SerializedThrift
- ): Option[AdMetadataContainer] =
- AdMetadataContainerSerializer.deserialize(serializedAdMetadataContainer).map { container =>
- AdMetadataContainer(
- removePromotedAttributionForPreroll = container.removePromotedAttributionForPreroll,
- sponsorshipCandidate = container.sponsorshipCandidate,
- sponsorshipOrganization = container.sponsorshipOrganization,
- sponsorshipOrganizationWebsite = container.sponsorshipOrganizationWebsite,
- sponsorshipType = container.sponsorshipType.map(convertSponsorshipType),
- disclaimerType = container.disclaimerType.map(convertDisclaimerType),
- skAdNetworkDataList = container.skAdNetworkDataList.map(convertSkAdNetworkDataList),
- unifiedCardOverride = container.unifiedCardOverride
- )
- }
-
- private def convertDisclosureType(disclosureType: ad.DisclosureType): DisclosureType =
- disclosureType match {
- case ad.DisclosureType.None => NoDisclosure
- case ad.DisclosureType.Political => Political
- case ad.DisclosureType.Earned => Earned
- case ad.DisclosureType.Issue => Issue
- case _ => throw new UnsupportedOperationException(s"Unsupported: $disclosureType")
- }
-
- private def convertSponsorshipType(sponsorshipType: ads.SponsorshipType): SponsorshipType =
- sponsorshipType match {
- case ads.SponsorshipType.Direct => DirectSponsorshipType
- case ads.SponsorshipType.Indirect => IndirectSponsorshipType
- case ads.SponsorshipType.NoSponsorship => NoSponsorshipSponsorshipType
- case _ => throw new UnsupportedOperationException(s"Unsupported: $sponsorshipType")
- }
-
- private def convertDisclaimerType(disclaimerType: ads.DisclaimerType): DisclaimerType =
- disclaimerType match {
- case ads.DisclaimerType.Political => DisclaimerPolitical
- case ads.DisclaimerType.Issue => DisclaimerIssue
- case _ => throw new UnsupportedOperationException(s"Unsupported: $disclaimerType")
- }
-
- private def convertSkAdNetworkDataList(
- skAdNetworkDataList: Seq[ads.SkAdNetworkData]
- ): Seq[SkAdNetworkData] = skAdNetworkDataList.map { sdAdNetwork =>
- SkAdNetworkData(
- version = sdAdNetwork.version,
- srcAppId = sdAdNetwork.srcAppId,
- dstAppId = sdAdNetwork.dstAppId,
- adNetworkId = sdAdNetwork.adNetworkId,
- campaignId = sdAdNetwork.campaignId,
- impressionTimeInMillis = sdAdNetwork.impressionTimeInMillis,
- nonce = sdAdNetwork.nonce,
- signature = sdAdNetwork.signature,
- fidelityType = sdAdNetwork.fidelityType
- )
- }
-
- private def convertClickTrackingInfo(clickTracking: ad.ClickTrackingInfo): ClickTrackingInfo =
- ClickTrackingInfo(
- urlParams = clickTracking.urlParams.getOrElse(Map.empty),
- urlOverride = clickTracking.urlOverride,
- urlOverrideType = clickTracking.urlOverrideType.map {
- case ad.UrlOverrideType.Unknown => UnknownUrlOverrideType
- case ad.UrlOverrideType.Dcm => DcmUrlOverrideType
- case ad.UrlOverrideType.EnumUnknownUrlOverrideType(value) =>
- throw new UnsupportedOperationException(s"Unsupported: $value")
- }
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala
deleted file mode 100644
index cb5ff66df..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class RichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- textBuilder: BaseStr[Query, Candidate],
- linkMap: Map[String, String],
- rtl: Option[Boolean],
- alignment: Option[RichTextAlignment],
- linkTypeMap: Map[String, UrlType] = Map.empty)
- extends BaseRichTextBuilder[Query, Candidate] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText = {
- RichTextMarkupUtil.richTextFromMarkup(
- text = textBuilder(query, candidate, candidateFeatures),
- linkMap = linkMap,
- rtl = rtl,
- alignment = alignment,
- linkTypeMap = linkTypeMap)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala
deleted file mode 100644
index dacb72b90..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong
-
-/*
- * RichTextMarkupUtil facilitates building a Product Mixer URT RichText object out of
- * a string with inline XML markup.
- *
- * This allows us to use a string like "Our system Product Mixer is the best". Using
- * inline markup like this is advantageous since the string can go through translation/localization and the
- * translators will move the tags around in each language as appropriate.
- *
- * This class is derived from the OCF (onboarding/serve)'s RichTextUtil, but they diverge because:
- * - We generate ProMix URT structures, not OCF URT structures
- * - The OCF supports some internal OCF tags, like
- * - The OCF has additional legacy support and processing that we don't need
- */
-
-object RichTextMarkupUtil {
-
- // Matches a anchor element, extracting the 'a' tag and the display text.
- // First group is the tag
- // Second group is the display text
- // Allows any character in the display text, but matches reluctantly
- private val LinkAnchorRegex = """(?i)(?s)(.*?)""".r
-
- // Matches a bold text section
- private val BoldRegex = """(?i)(?s)(.*?)""".r
-
- def richTextFromMarkup(
- text: String,
- linkMap: Map[String, String],
- rtl: Option[Boolean] = None,
- alignment: Option[RichTextAlignment] = None,
- linkTypeMap: Map[String, UrlType] = Map.empty
- ): RichText = {
-
- // Mutable!
- var currentText = text
- val entities = scala.collection.mutable.ArrayBuffer.empty[RichTextEntity]
-
- // Using a while loop since we want to execute the regex after each iteration, so our indexes remain consistent
-
- // Handle Links
- var matchOpt = LinkAnchorRegex.findFirstMatchIn(currentText)
- while (matchOpt.isDefined) {
- matchOpt.foreach { linkMatch =>
- val tag = linkMatch.group(1)
- val displayText = linkMatch.group(2)
-
- currentText = currentText.substring(0, linkMatch.start) + displayText + currentText
- .substring(linkMatch.end)
-
- adjustEntities(
- entities,
- linkMatch.start,
- linkMatch.end - (linkMatch.start + displayText.length))
-
- entities.append(
- RichTextEntity(
- fromIndex = linkMatch.start,
- toIndex = linkMatch.start + displayText.length,
- ref = linkMap.get(tag).map { url =>
- Url(
- urlType = linkTypeMap.getOrElse(tag, ExternalUrl),
- url = url
- )
- },
- format = None
- )
- )
- }
- matchOpt = LinkAnchorRegex.findFirstMatchIn(currentText)
- }
-
- // Handle Bold
- matchOpt = BoldRegex.findFirstMatchIn(currentText)
- while (matchOpt.isDefined) {
- matchOpt.foreach { boldMatch =>
- val text = boldMatch.group(1)
-
- currentText =
- currentText.substring(0, boldMatch.start) + text + currentText.substring(boldMatch.end)
-
- adjustEntities(entities, boldMatch.start, boldMatch.end - (boldMatch.start + text.length))
-
- entities.append(
- RichTextEntity(
- fromIndex = boldMatch.start,
- toIndex = boldMatch.start + text.length,
- ref = None,
- format = Some(Strong),
- )
- )
- }
-
- matchOpt = BoldRegex.findFirstMatchIn(currentText)
- }
-
- RichText(
- currentText,
- entities.sortBy(_.fromIndex).toList, // always return immutable copies!
- rtl,
- alignment
- )
- }
-
- /* When we create a new entity, we need to adjust
- * any already existing entities that have been moved.
- * Entities cannot overlap, so we can just compare start positions.
- */
- private def adjustEntities(
- entities: scala.collection.mutable.ArrayBuffer[RichTextEntity],
- start: Int,
- length: Int
- ): Unit = {
- for (i <- entities.indices) {
- if (entities(i).fromIndex > start) {
- val old = entities(i)
- entities.update(
- i,
- entities(i).copy(
- fromIndex = old.fromIndex - length,
- toIndex = old.toIndex - length
- ))
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala
deleted file mode 100644
index 503f0841c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-import com.twitter.twittertext.Extractor
-
-trait RichTextReferenceObjectBuilder {
- def apply(entity: Extractor.Entity): Option[ReferenceObject]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala
deleted file mode 100644
index 6fc39d5a4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait RichTextRtlOptionBuilder[-Query <: PipelineQuery] {
- def apply(query: Query): Option[Boolean]
-}
-
-case class StaticRichTextRtlOptionBuilder[-Query <: PipelineQuery](rtlOption: Option[Boolean])
- extends RichTextRtlOptionBuilder[Query] {
- override def apply(query: Query): Option[Boolean] = rtlOption
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala
deleted file mode 100644
index 64054559a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticRichTextBuilder(richText: RichText)
- extends BaseRichTextBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): RichText = richText
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala
deleted file mode 100644
index ca27c7e14..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextReferenceObjectBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text.TwitterTextEntityProcessor.DefaultReferenceObjectBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag
-import com.twitter.twittertext.Extractor
-import scala.collection.convert.ImplicitConversions._
-
-object TwitterTextEntityProcessor {
- object DefaultReferenceObjectBuilder extends RichTextReferenceObjectBuilder {
- def apply(twitterEntity: Extractor.Entity): Option[ReferenceObject] = {
- twitterEntity.getType match {
- case Extractor.Entity.Type.URL =>
- Some(Url(ExternalUrl, twitterEntity.getValue))
- case Extractor.Entity.Type.HASHTAG =>
- Some(RichTextHashtag(twitterEntity.getValue))
- case Extractor.Entity.Type.CASHTAG =>
- Some(RichTextCashtag(twitterEntity.getValue))
- case _ => None
- }
- }
- }
-}
-
-/**
- * Add the corresponding [[RichTextEntity]] extraction logic into [[TwitterTextRenderer]].
- * The [[TwitterTextRenderer]] after being processed will extract the defined entities.
- */
-case class TwitterTextEntityProcessor(
- twitterTextReferenceObjectBuilder: RichTextReferenceObjectBuilder = DefaultReferenceObjectBuilder)
- extends TwitterTextRendererProcessor {
-
- private[this] val extractor = new Extractor()
-
- def process(
- twitterTextRenderer: TwitterTextRenderer
- ): TwitterTextRenderer = {
- val twitterEntities = extractor.extractEntitiesWithIndices(twitterTextRenderer.text)
-
- twitterEntities.foreach { twitterEntity =>
- twitterTextReferenceObjectBuilder(twitterEntity).foreach { refObject =>
- twitterTextRenderer.setRefObject(twitterEntity.getStart, twitterEntity.getEnd, refObject)
- }
- }
- twitterTextRenderer
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala
deleted file mode 100644
index cf36eecc6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong
-import scala.collection.mutable
-
-object TwitterTextFormatProcessor {
- lazy val defaultFormatProcessor = TwitterTextFormatProcessor()
-}
-
-/**
- * Add the corresponding [[RichTextFormat]] extraction logic into [[TwitterTextRenderer]].
- * The [[TwitterTextRenderer]] after being processed will extract the defined entities.
- */
-case class TwitterTextFormatProcessor(
- formats: Set[RichTextFormat] = Set(Plain, Strong),
-) extends TwitterTextRendererProcessor {
-
- private val formatMap = formats.map { format => format.name.toLowerCase -> format }.toMap
-
- private[this] val formatMatcher = {
- val formatNames = formatMap.keys.toSet
- s"<(/?)(${formatNames.mkString("|")})>".r
- }
-
- def renderText(text: String): RichText = {
- process(TwitterTextRenderer(text)).build
- }
-
- def process(richTextBuilder: TwitterTextRenderer): TwitterTextRenderer = {
- val text = richTextBuilder.text
- val nodeStack = mutable.ArrayStack[(RichTextFormat, Int)]()
- var offset = 0
-
- formatMatcher.findAllMatchIn(text).foreach { m =>
- formatMap.get(m.group(2)) match {
- case Some(format) => {
- if (m.group(1).nonEmpty) {
- if (!nodeStack.headOption.exists {
- case (formatFromStack, _) => formatFromStack == format
- }) {
- throw UnmatchedFormatTag(format)
- }
- val (_, startIndex) = nodeStack.pop
- richTextBuilder.mergeFormat(startIndex, m.start + offset, format)
- } else {
- nodeStack.push((format, m.start + offset))
- }
- richTextBuilder.remove(m.start + offset, m.end + offset)
- offset -= m.end - m.start
- }
- case _ => // if format is not found, skip this format
- }
- }
-
- if (nodeStack.nonEmpty) {
- throw UnmatchedFormatTag(nodeStack.head._1)
- }
-
- richTextBuilder
- }
-}
-
-case class UnmatchedFormatTag(format: RichTextFormat)
- extends Exception(s"Unmatched format start and end tags for $format")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala
deleted file mode 100644
index 53a534255..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala
+++ /dev/null
@@ -1,390 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat
-import scala.annotation.tailrec
-import scala.collection.mutable
-
-object TwitterTextRenderer {
-
- /**
- * Creates a new [[TwitterTextRenderer]] instance.
- * @param text The initial text representation
- * @param rtl Defines whether this text is in an RTL language
- * @param alignment Assigns the [[RichTextAlignment]] of the given text for display
- * @return A new [[TwitterTextRenderer]] instance
- */
- def apply(
- text: String,
- rtl: Option[Boolean] = None,
- alignment: Option[RichTextAlignment] = None
- ): TwitterTextRenderer = {
- TwitterTextRenderer(rtl, alignment).append(text)
- }
-
- /**
- * Creates a new [[TwitterTextRenderer]] instance from a product-mixer [[RichText]] object.
- * Converts Unicode entity indexes into JVM String indexes.
- * @param richText The product-mixer [[RichText]] representation
- * @return A new [[TwitterTextRenderer]] instance
- */
- def fromRichText(richText: RichText): TwitterTextRenderer = {
- val builder = TwitterTextRenderer(richText.text, richText.rtl, richText.alignment)
- richText.entities.foreach { e =>
- val startIndex = richText.text.offsetByCodePoints(0, e.fromIndex)
- val endIndex = richText.text.offsetByCodePoints(0, e.toIndex)
- e.format.foreach { f =>
- builder.setFormat(startIndex, endIndex, f)
- }
- e.ref.foreach { r =>
- builder.setRefObject(startIndex, endIndex, r)
- }
- }
- builder
- }
-
- private def buildRichTextEntity(
- text: String,
- entity: TwitterTextRendererEntity[_]
- ): RichTextEntity = {
- val fromIndex = text.codePointCount(0, entity.startIndex)
- val toIndex = text.codePointCount(0, entity.endIndex)
-
- entity.value match {
- case format: RichTextFormat =>
- RichTextEntity(fromIndex, toIndex, ref = None, format = Some(format))
- case ref: ReferenceObject =>
- RichTextEntity(fromIndex, toIndex, ref = Some(ref), format = None)
- }
- }
-}
-
-case class TwitterTextRenderer(
- rtl: Option[Boolean],
- alignment: Option[RichTextAlignment],
-) {
- private[this] val textBuilder = new mutable.StringBuilder()
-
- private[richtext] val formatBuffer =
- mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]()
- private[richtext] val refObjectBuffer =
- mutable.ArrayBuffer[TwitterTextRendererEntity[ReferenceObject]]()
-
- /**
- * Appends a string with attached [[RichTextFormat]] and [[ReferenceObject]] information.
- * @param string The text to append to the end of the existing text
- * @param format The [[RichTextFormat]] assigned to the new text
- * @param refObject The [[ReferenceObject]] assigned to the new text
- * @return this
- */
- def append(
- string: String,
- format: Option[RichTextFormat] = None,
- refObject: Option[ReferenceObject] = None
- ): TwitterTextRenderer = {
- if (string.nonEmpty) {
- val start = textBuilder.length
- val end = start + string.length
- format.foreach { f =>
- formatBuffer.append(TwitterTextRendererEntity(start, end, f))
- }
- refObject.foreach { r =>
- refObjectBuffer.append(TwitterTextRendererEntity(start, end, r))
- }
- textBuilder.append(string)
- }
- this
- }
-
- /**
- * Builds a new [[RichText]] thrift instance with Unicode entity ranges.
- */
- def build: RichText = {
- val richTextString = this.text
- val richTextEntities = this.entities
- .map { e =>
- TwitterTextRenderer.buildRichTextEntity(richTextString, e)
- }
-
- RichText(
- text = richTextString,
- rtl = rtl,
- alignment = alignment,
- entities = richTextEntities.toList
- )
- }
-
- /**
- * Modifies the TwitterTextRenderer with the provided [[TwitterTextRendererProcessor]]
- */
- def transform(twitterTextProcessor: TwitterTextRendererProcessor): TwitterTextRenderer = {
- twitterTextProcessor.process(this)
- }
-
- /**
- * Builds and returns a sorted list of [[TwitterTextRendererEntity]] with JVM String index entity ranges.
- */
- def entities: Seq[TwitterTextRendererEntity[_]] = {
- buildEntities(formatBuffer.toList, refObjectBuffer.toList)
- }
-
- /**
- * Assigns a [[RichTextFormat]] to the given range while keeping existing formatting information.
- * New formatting will only be assigned to unformatted text ranges.
- * @param start Start index to apply formatting (inclusive)
- * @param end End index to apply formatting (exclusive)
- * @param format The format to assign
- * @return this
- */
- def mergeFormat(start: Int, end: Int, format: RichTextFormat): TwitterTextRenderer = {
- validateRange(start, end)
- var injectionIndex: Option[Int] = None
- var entity = TwitterTextRendererEntity(start, end, format)
-
- val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]()
- val iterator = formatBuffer.zipWithIndex.reverseIterator
-
- while (iterator.hasNext && injectionIndex.isEmpty) {
- iterator.next match {
- case (e, i) if e.startIndex >= end =>
- buffer.append(e)
-
- case (e, i) if e.enclosedIn(entity.startIndex, entity.endIndex) =>
- val endEntity = entity.copy(startIndex = e.endIndex)
- if (endEntity.nonEmpty) { buffer.append(endEntity) }
- buffer.append(e)
- entity = entity.copy(endIndex = e.startIndex)
-
- case (e, i) if e.encloses(entity.startIndex, entity.endIndex) =>
- buffer.append(e.copy(startIndex = entity.endIndex))
- buffer.append(e.copy(endIndex = entity.startIndex))
- injectionIndex = Some(i + 1)
-
- case (e, i) if e.startsBetween(entity.startIndex, entity.endIndex) =>
- buffer.append(e)
- entity = entity.copy(endIndex = e.startIndex)
-
- case (e, i) if e.endsBetween(entity.startIndex, entity.endIndex) =>
- buffer.append(e)
- entity = entity.copy(startIndex = e.endIndex)
- injectionIndex = Some(i + 1)
-
- case (e, i) if e.endIndex <= entity.startIndex =>
- buffer.append(e)
- injectionIndex = Some(i + 1)
-
- case _ => // do nothing
- }
- }
-
- val index = injectionIndex.map(_ - 1).getOrElse(0)
- formatBuffer.remove(index, formatBuffer.length - index)
- formatBuffer.appendAll(buffer.reverse)
-
- if (entity.nonEmpty) {
- formatBuffer.insert(injectionIndex.getOrElse(0), entity)
- }
-
- this
- }
-
- /**
- * Removes text, formatting, and refObject information from the given range.
- * @param start Start index to apply formatting (inclusive)
- * @param end End index to apply formatting (exclusive)
- * @return this
- */
- def remove(start: Int, end: Int): TwitterTextRenderer = replace(start, end, "")
-
- /**
- * Replaces text, formatting, and refObject information in the given range.
- * @param start Start index to apply formatting (inclusive)
- * @param end End index to apply formatting (exclusive)
- * @param string The new text to insert
- * @param format The [[RichTextFormat]] assigned to the new text
- * @param refObject The [[ReferenceObject]] assigned to the new text
- * @return this
- */
- def replace(
- start: Int,
- end: Int,
- string: String,
- format: Option[RichTextFormat] = None,
- refObject: Option[ReferenceObject] = None
- ): TwitterTextRenderer = {
- validateRange(start, end)
-
- val newEnd = start + string.length
- val formatInjectIndex = removeAndOffsetFormats(start, end, string.length)
- val refObjectInjectIndex = removeAndOffsetRefObjects(start, end, string.length)
- format.foreach { f =>
- formatBuffer.insert(formatInjectIndex, TwitterTextRendererEntity(start, newEnd, f))
- }
- refObject.foreach { r =>
- refObjectBuffer.insert(refObjectInjectIndex, TwitterTextRendererEntity(start, newEnd, r))
- }
- textBuilder.replace(start, end, string)
-
- this
- }
-
- /**
- * Assigns a [[RichTextFormat]] to the given range. Trims existing format ranges that overlap the
- * new format range. Removes format ranges that fall within the new range.
- * @param start Start index to apply formatting (inclusive)
- * @param end End index to apply formatting (exclusive)
- * @param format The format to assign
- * @return this
- */
- def setFormat(start: Int, end: Int, format: RichTextFormat): TwitterTextRenderer = {
- validateRange(start, end)
- val bufferIndex = removeAndOffsetFormats(start, end, end - start)
- formatBuffer.insert(bufferIndex, TwitterTextRendererEntity(start, end, format))
-
- this
- }
-
- private[this] def removeAndOffsetFormats(start: Int, end: Int, newSize: Int): Int = {
- val newEnd = start + newSize
- val offset = newEnd - end
- var injectionIndex: Option[Int] = None
-
- val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]()
- val iterator = formatBuffer.zipWithIndex.reverseIterator
-
- while (iterator.hasNext && injectionIndex.isEmpty) {
- iterator.next match {
- case (e, i) if e.startIndex >= end =>
- buffer.append(e.offset(offset))
- case (e, i) if e.encloses(start, end) =>
- buffer.append(e.copy(startIndex = newEnd, endIndex = e.endIndex + offset))
- buffer.append(e.copy(endIndex = e.endIndex + offset))
- injectionIndex = Some(i + 1)
- case (e, i) if e.endsBetween(start, end) =>
- buffer.append(e.copy(endIndex = start))
- injectionIndex = Some(i + 1)
- case (e, i) if e.startsBetween(start, end) =>
- buffer.append(e.copy(startIndex = newEnd, endIndex = e.endIndex + offset))
- case (e, i) if e.endIndex <= start =>
- buffer.append(e)
- injectionIndex = Some(i + 1)
- case _ => // do nothing
- }
- }
- val index = injectionIndex.map(_ - 1).getOrElse(0)
- formatBuffer.remove(index, formatBuffer.length - index)
- formatBuffer.appendAll(buffer.reverse)
-
- injectionIndex.getOrElse(0)
- }
-
- private[this] def validateRange(start: Int, end: Int): Unit = {
- require(
- start >= 0 && start < textBuilder.length && end > start && end <= textBuilder.length,
- s"The start ($start) and end ($end) indexes must be within the text range (0..${textBuilder.length})"
- )
- }
-
- /**
- * Assigns a [[ReferenceObject]] to the given range. Since it makes little sense to trim object
- * ranges, existing intersecting or overlapping ranges are removed entirely.
- * @param start Start index to apply formatting (inclusive)
- * @param end End index to apply formatting (exclusive)
- * @param refObject The [[ReferenceObject]] to assign
- * @return this
- */
- def setRefObject(start: Int, end: Int, refObject: ReferenceObject): TwitterTextRenderer = {
- validateRange(start, end)
- val bufferIndex = removeAndOffsetRefObjects(start, end, end - start)
- refObjectBuffer.insert(bufferIndex, TwitterTextRendererEntity(start, end, refObject))
-
- this
- }
-
- private[this] def removeAndOffsetRefObjects(start: Int, end: Int, newSize: Int): Int = {
- val newEnd = start + newSize
- val offset = newEnd - end
- var injectionIndex: Option[Int] = None
-
- val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[ReferenceObject]]()
- val iterator = refObjectBuffer.zipWithIndex.reverseIterator
-
- while (iterator.hasNext && injectionIndex.isEmpty) {
- iterator.next match {
- case (e, i) if e.startIndex >= end => buffer.append(e.offset(offset))
- case (e, i) if e.endIndex <= start => injectionIndex = Some(i + 1)
- case _ => // do nothing
- }
- }
- val index = injectionIndex.getOrElse(0)
- refObjectBuffer.remove(index, refObjectBuffer.length - index)
- refObjectBuffer.appendAll(buffer.reverse)
-
- index
- }
-
- /**
- * Builds and returns the full TwitterTextRenderer text with any changes applied to the builder instance.
- */
- def text: String = {
- textBuilder.mkString
- }
-
- @tailrec
- private def buildEntities(
- formats: List[TwitterTextRendererEntity[RichTextFormat]],
- refs: List[TwitterTextRendererEntity[ReferenceObject]],
- acc: List[TwitterTextRendererEntity[_]] = List()
- ): Seq[TwitterTextRendererEntity[_]] = {
- (formats, refs) match {
- case (Nil, Nil) => acc
- case (remainingFormats, Nil) => acc ++ remainingFormats
- case (Nil, remainingRefs) => acc ++ remainingRefs
-
- case (format +: remainingFormats, ref +: remainingRefs)
- if format.startIndex < ref.startIndex || (format.startIndex == ref.startIndex && format.endIndex < ref.endIndex) =>
- buildEntities(remainingFormats, refs, acc :+ format)
-
- case (format +: remainingFormats, ref +: remainingRefs)
- if format.startIndex == ref.startIndex && format.endIndex == ref.endIndex =>
- buildEntities(remainingFormats, remainingRefs, acc :+ format :+ ref)
-
- case (_, ref +: remainingRefs) =>
- buildEntities(formats, remainingRefs, acc :+ ref)
- }
- }
-}
-
-case class TwitterTextRendererEntity[+T] private[richtext] (
- startIndex: Int,
- endIndex: Int,
- value: T) {
- require(startIndex <= endIndex, "startIndex must be <= than endIndex")
-
- def nonEmpty: Boolean = !isEmpty
-
- def isEmpty: Boolean = startIndex == endIndex
-
- private[richtext] def enclosedIn(start: Int, end: Int): Boolean = {
- start <= startIndex && endIndex <= end
- }
-
- private[richtext] def encloses(start: Int, end: Int): Boolean = {
- startIndex < start && end < endIndex
- }
-
- private[richtext] def endsBetween(start: Int, end: Int): Boolean = {
- start < endIndex && endIndex <= end && startIndex < start
- }
-
- private[richtext] def offset(num: Int): TwitterTextRendererEntity[T] = {
- copy(startIndex = startIndex + num, endIndex = endIndex + num)
- }
-
- private[richtext] def startsBetween(start: Int, end: Int): Boolean = {
- startIndex >= start && startIndex < end && endIndex > end
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala
deleted file mode 100644
index 5e5f45659..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text
-
-trait TwitterTextRendererProcessor {
- def process(twitterTextRichTextBuilder: TwitterTextRenderer): TwitterTextRenderer
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala
deleted file mode 100644
index 50422a335..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextReferenceObjectBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextRtlOptionBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.StaticRichTextRtlOptionBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text.TwitterTextEntityProcessor.DefaultReferenceObjectBuilder
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class TwitterTextRichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- stringBuilder: BaseStr[Query, Candidate],
- alignment: Option[RichTextAlignment] = None,
- formats: Set[RichTextFormat] = Set(Plain, Strong),
- twitterTextRtlOptionBuilder: RichTextRtlOptionBuilder[Query] =
- StaticRichTextRtlOptionBuilder[Query](None),
- twitterTextReferenceObjectBuilder: RichTextReferenceObjectBuilder = DefaultReferenceObjectBuilder)
- extends BaseRichTextBuilder[Query, Candidate] {
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText = {
- val twitterTextRenderer = TwitterTextRenderer(
- text = stringBuilder(query, candidate, candidateFeatures),
- rtl = twitterTextRtlOptionBuilder(query),
- alignment = alignment)
-
- twitterTextRenderer
- .transform(TwitterTextFormatProcessor(formats))
- .transform(TwitterTextEntityProcessor(twitterTextReferenceObjectBuilder))
- .build
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala
deleted file mode 100644
index d96551bc6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.service.{thriftscala => t}
-
-/**
- * Use this Builder to create Product Mixer [[SocialContext]] objects when you have a
- * Timeline Service Thrift [[SocialContext]] feature that you want to convert
- */
-case class FeatureSocialContextBuilder(
- socialContextFeature: Feature[_, Option[t.SocialContext]])
- extends BaseSocialContextBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): Option[SocialContext] = {
- candidateFeatures.getOrElse(socialContextFeature, None).map {
- case t.SocialContext.GeneralContext(context) =>
- val contextType = context.contextType match {
- case t.ContextType.Like => LikeGeneralContextType
- case t.ContextType.Follow => FollowGeneralContextType
- case t.ContextType.Moment => MomentGeneralContextType
- case t.ContextType.Reply => ReplyGeneralContextType
- case t.ContextType.Conversation => ConversationGeneralContextType
- case t.ContextType.Pin => PinGeneralContextType
- case t.ContextType.TextOnly => TextOnlyGeneralContextType
- case t.ContextType.Facepile => FacePileGeneralContextType
- case t.ContextType.Megaphone => MegaPhoneGeneralContextType
- case t.ContextType.Bird => BirdGeneralContextType
- case t.ContextType.Feedback => FeedbackGeneralContextType
- case t.ContextType.Topic => TopicGeneralContextType
- case t.ContextType.List => ListGeneralContextType
- case t.ContextType.Retweet => RetweetGeneralContextType
- case t.ContextType.Location => LocationGeneralContextType
- case t.ContextType.Community => CommunityGeneralContextType
- case t.ContextType.SmartBlockExpiration => SmartblockExpirationGeneralContextType
- case t.ContextType.Trending => TrendingGeneralContextType
- case t.ContextType.Sparkle => SparkleGeneralContextType
- case t.ContextType.Spaces => SpacesGeneralContextType
- case t.ContextType.ReplyPin => ReplyPinGeneralContextType
- case t.ContextType.NewUser => NewUserGeneralContextType
- case t.ContextType.EnumUnknownContextType(field) =>
- throw new UnsupportedOperationException(s"Unknown context type: $field")
- }
-
- val landingUrl = context.landingUrl.map { url =>
- val endpointOptions = url.urtEndpointOptions.map { options =>
- UrtEndpointOptions(
- requestParams = options.requestParams.map(_.toMap),
- title = options.title,
- cacheId = options.cacheId,
- subtitle = options.subtitle
- )
- }
-
- val urlType = url.urlType match {
- case t.UrlType.ExternalUrl => ExternalUrl
- case t.UrlType.DeepLink => DeepLink
- case t.UrlType.UrtEndpoint => UrtEndpoint
- case t.UrlType.EnumUnknownUrlType(field) =>
- throw new UnsupportedOperationException(s"Unknown url type: $field")
- }
-
- Url(urlType = urlType, url = url.url, urtEndpointOptions = endpointOptions)
- }
-
- GeneralContext(
- text = context.text,
- contextType = contextType,
- url = context.url,
- contextImageUrls = context.contextImageUrls.map(_.toList),
- landingUrl = landingUrl
- )
- case t.SocialContext.TopicContext(context) =>
- val functionalityType = context.functionalityType match {
- case t.TopicContextFunctionalityType.Basic =>
- BasicTopicContextFunctionalityType
- case t.TopicContextFunctionalityType.Recommendation =>
- RecommendationTopicContextFunctionalityType
- case t.TopicContextFunctionalityType.RecWithEducation =>
- RecWithEducationTopicContextFunctionalityType
- case t.TopicContextFunctionalityType.EnumUnknownTopicContextFunctionalityType(field) =>
- throw new UnsupportedOperationException(s"Unknown functionality type: $field")
- }
-
- TopicContext(
- topicId = context.topicId,
- functionalityType = Some(functionalityType)
- )
- case t.SocialContext.UnknownUnionField(field) =>
- throw new UnsupportedOperationException(s"Unknown social context: $field")
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala
deleted file mode 100644
index c3e9e9919..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseModuleStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseModuleSocialContextBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * This class works the same as [[GeneralSocialContextBuilder]] but passes a list of candidates
- * into [[BaseModuleStr]] when rendering the string.
- */
-case class GeneralModuleSocialContextBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]
-](
- textBuilder: BaseModuleStr[Query, Candidate],
- contextType: GeneralContextType,
- url: Option[String] = None,
- contextImageUrls: Option[List[String]] = None,
- landingUrl: Option[Url] = None)
- extends BaseModuleSocialContextBuilder[Query, Candidate] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[GeneralContext] =
- Some(
- GeneralContext(
- text = textBuilder(query, candidates),
- contextType = contextType,
- url = url,
- contextImageUrls = contextImageUrls,
- landingUrl = landingUrl))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala
deleted file mode 100644
index ef2221468..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class GeneralSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- textBuilder: BaseStr[Query, Candidate],
- contextType: GeneralContextType,
- url: Option[String] = None,
- contextImageUrls: Option[List[String]] = None,
- landingUrl: Option[Url] = None)
- extends BaseSocialContextBuilder[Query, Candidate] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[GeneralContext] =
- Some(
- GeneralContext(
- text = textBuilder(query, candidate, candidateFeatures),
- contextType = contextType,
- url = url,
- contextImageUrls = contextImageUrls,
- landingUrl = landingUrl))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala
deleted file mode 100644
index edcc07fcd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context
-
-import com.twitter.hermit.{thriftscala => h}
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FollowGeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LocationGeneralContextType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.NewUserGeneralContextType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class WhoToFollowSocialContextBuilder(
- socialTextFeature: Feature[_, Option[String]],
- contextTypeFeature: Feature[_, Option[h.ContextType]])
- extends BaseSocialContextBuilder[PipelineQuery, UserCandidate] {
-
- def apply(
- query: PipelineQuery,
- candidate: UserCandidate,
- candidateFeatures: FeatureMap
- ): Option[GeneralContext] = {
- val socialTextOpt = candidateFeatures.getOrElse(socialTextFeature, None)
- val contextTypeOpt = convertContextType(candidateFeatures.getOrElse(contextTypeFeature, None))
-
- (socialTextOpt, contextTypeOpt) match {
- case (Some(socialText), Some(contextType)) if socialText.nonEmpty =>
- Some(
- GeneralContext(
- text = socialText,
- contextType = contextType,
- url = None,
- contextImageUrls = None,
- landingUrl = None))
- case _ => None
- }
- }
-
- private def convertContextType(contextType: Option[h.ContextType]): Option[GeneralContextType] =
- contextType match {
- case Some(h.ContextType.Geo) => Some(LocationGeneralContextType)
- case Some(h.ContextType.Social) => Some(FollowGeneralContextType)
- case Some(h.ContextType.NewUser) => Some(NewUserGeneralContextType)
- case _ => None
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala
deleted file mode 100644
index 0abb2ec63..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseModuleStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter.BaseModuleStringCenterPlaceholderBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stringcenter.client.StringCenter
-import com.twitter.stringcenter.client.core.ExternalString
-
-/**
- * This class works the same as [[Str]] but passes in a list of candidates to the
- * [[BaseModuleStringCenterPlaceholderBuilder]] when building the placeholders.
- */
-case class ModuleStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- text: ExternalString,
- stringCenter: StringCenter,
- stringCenterPlaceholderBuilder: Option[
- BaseModuleStringCenterPlaceholderBuilder[Query, Candidate]
- ] = None)
- extends BaseModuleStr[Query, Candidate] {
-
- def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): String = {
- val placeholderMapOpt =
- stringCenterPlaceholderBuilder.map(_.apply(query, candidates))
- stringCenter.prepare(
- externalString = text,
- placeholders = placeholderMapOpt.getOrElse(Map.empty[String, Any])
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala
deleted file mode 100644
index 6f5a6c3b3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter.BaseStringCenterPlaceholderBuilder
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stringcenter.client.StringCenter
-import com.twitter.stringcenter.client.core.ExternalString
-
-case class StrStatic(
- text: String)
- extends BaseStr[PipelineQuery, UniversalNoun[Any]] {
- def apply(
- query: PipelineQuery,
- candidate: UniversalNoun[Any],
- candidateFeatures: FeatureMap
- ): String = text
-}
-
-case class Str[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- text: ExternalString,
- stringCenter: StringCenter,
- stringCenterPlaceholderBuilder: Option[BaseStringCenterPlaceholderBuilder[Query, Candidate]] =
- None)
- extends BaseStr[Query, Candidate] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): String = {
- val placeholderMapOpt =
- stringCenterPlaceholderBuilder.map(_.apply(query, candidate, candidateFeatures))
- stringCenter.prepare(
- externalString = text,
- placeholders = placeholderMapOpt.getOrElse(Map.empty[String, Any])
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala
deleted file mode 100644
index bc9632e5a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class FeatureModuleDisplayTypeBuilder(
- displayTypeFeature: Feature[_, Option[ModuleDisplayType]],
- defaultDisplayType: ModuleDisplayType = VerticalConversation)
- extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleDisplayType = candidates.headOption
- .flatMap(_.features.getOrElse(displayTypeFeature, None))
- .getOrElse(defaultDisplayType)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala
deleted file mode 100644
index fd234de7c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ModuleDynamicShowMoreBehaviorRevealByCountBuilder(
- initialItemsCount: Int,
- showMoreItemsCount: Int)
- extends BaseModuleShowMoreBehaviorBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleShowMoreBehavior = ModuleShowMoreBehaviorRevealByCount(
- initialItemsCount = initialItemsCount,
- showMoreItemsCount = showMoreItemsCount
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala
deleted file mode 100644
index 886825f2d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-
-case class ModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- textBuilder: BaseStr[Query, Candidate],
- urlBuilder: Option[BaseUrlBuilder[Query, Candidate]])
- extends BaseModuleFooterBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleFooter] = {
- candidates.headOption.map { candidate =>
- ModuleFooter(
- text = textBuilder(query, candidate.candidate, candidate.features),
- landingUrl = urlBuilder.map(_.apply(query, candidate.candidate, candidate.features))
- )
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala
deleted file mode 100644
index fbe256d69..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon.BaseHorizonIconBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseModuleSocialContextBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- textBuilder: BaseStr[Query, Candidate],
- isSticky: Option[Boolean] = None,
- moduleHeaderIconBuilder: Option[BaseHorizonIconBuilder[Query, Candidate]] = None,
- customIcon: Option[ImageVariant] = None,
- moduleSocialContextBuilder: Option[BaseModuleSocialContextBuilder[Query, Candidate]] = None,
- moduleHeaderDisplayTypeBuilder: BaseModuleHeaderDisplayTypeBuilder[Query, Candidate] =
- ModuleHeaderDisplayTypeBuilder(Classic))
- extends BaseModuleHeaderBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleHeader] = {
- val firstCandidate = candidates.head
- Some(
- ModuleHeader(
- text = textBuilder(query, firstCandidate.candidate, firstCandidate.features),
- sticky = isSticky,
- customIcon = customIcon,
- socialContext = moduleSocialContextBuilder.flatMap(_.apply(query, candidates)),
- icon = moduleHeaderIconBuilder.flatMap(_.apply(query, candidates)),
- moduleHeaderDisplayType = moduleHeaderDisplayTypeBuilder(query, candidates),
- )
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala
deleted file mode 100644
index bc0fffa8c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ModuleHeaderDisplayTypeBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]
-](
- moduleHeaderDisplayType: ModuleHeaderDisplayType = Classic)
- extends BaseModuleHeaderDisplayTypeBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleHeaderDisplayType = moduleHeaderDisplayType
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala
deleted file mode 100644
index a885632e0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-/**
- * This trait is used for Module ID generation. Clients are safe to ignore this code unless they
- * have a specific use case that requires hard-coded, specific, module ids. In that scenario,
- * they can use the [[ManualModuleId]] case class.
- */
-sealed trait ModuleIdGeneration {
- val moduleId: Long
-}
-
-object ModuleIdGeneration {
- def apply(moduleId: Long): ModuleIdGeneration = moduleId match {
- case moduleId if AutomaticUniqueModuleId.isAutomaticUniqueModuleId(moduleId) =>
- AutomaticUniqueModuleId(moduleId)
- case moduleId => ManualModuleId(moduleId)
- }
-}
-
-/**
- * Generate unique Ids for each module, which results in unique URT entryIds
- * for each module even if they share the same entryNamespace.
- * This is the default and recommended use case.
- * Note that the module Id value is just a placeholder
- */
-case class AutomaticUniqueModuleId private (moduleId: Long = 0L) extends ModuleIdGeneration {
- def withOffset(offset: Long): AutomaticUniqueModuleId = copy(
- AutomaticUniqueModuleId.idRange.min + offset)
-}
-
-object AutomaticUniqueModuleId {
- // We use a specific numeric range to track whether IDs should be automatically generated.
- val idRange: Range = Range(-10000, -1000)
-
- def apply(): AutomaticUniqueModuleId = AutomaticUniqueModuleId(idRange.min)
-
- def isAutomaticUniqueModuleId(moduleId: Long): Boolean = idRange.contains(moduleId)
-}
-
-/**
- * ManualModuleId should normally not be required, but is helpful if the
- * entryId of the module must be controlled. A scenario where this may be
- * required is if a single candidate source returns multiple modules, and
- * each module has the same presentation (e.g. Header, Footer). By setting
- * different IDs, we signal to the platform that each module should be separate
- * by using a different manual Id.
- */
-case class ManualModuleId(override val moduleId: Long) extends ModuleIdGeneration {
- // Negative module IDs are reserved for internal usage
- if (moduleId < 0) throw new IllegalArgumentException("moduleId must be a positive number")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala
deleted file mode 100644
index 19bce376a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.timelines.configapi.Param
-
-case class ModuleShowMoreBehaviorRevealByCountBuilder(
- initialItemsCountParam: Param[Int],
- showMoreItemsCountParam: Param[Int])
- extends BaseModuleShowMoreBehaviorBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidate: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleShowMoreBehavior = {
- ModuleShowMoreBehaviorRevealByCount(
- initialItemsCount = query.params(initialItemsCountParam),
- showMoreItemsCount = query.params(showMoreItemsCountParam)
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala
deleted file mode 100644
index 36654335a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-case class ParamGatedModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- enableParam: Param[Boolean],
- enabledBuilder: BaseModuleFooterBuilder[Query, Candidate],
- defaultBuilder: Option[BaseModuleFooterBuilder[Query, Candidate]] = None)
- extends BaseModuleFooterBuilder[Query, Candidate] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleFooter] = {
- if (query.params(enableParam)) {
- enabledBuilder(query, candidates)
- } else {
- defaultBuilder.flatMap(_.apply(query, candidates))
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala
deleted file mode 100644
index 44598b093..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-case class ParamGatedModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- enableParam: Param[Boolean],
- enabledBuilder: BaseModuleHeaderBuilder[Query, Candidate],
- defaultBuilder: Option[BaseModuleHeaderBuilder[Query, Candidate]] = None)
- extends BaseModuleHeaderBuilder[Query, Candidate] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleHeader] = {
- if (query.params(enableParam)) {
- enabledBuilder(query, candidates)
- } else {
- defaultBuilder.flatMap(_.apply(query, candidates))
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala
deleted file mode 100644
index 1e83a032e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.CompactCarousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ConversationTree
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Vertical
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalGrid
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalWithContextLine
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-object WhoToFollowModuleDisplayType extends Enumeration {
- type ModuleDisplayType = Value
-
- val Carousel = Value
- val CompactCarousel = Value
- val ConversationTree = Value
- val GridCarousel = Value
- val Vertical = Value
- val VerticalConversation = Value
- val VerticalGrid = Value
- val VerticalWithContextLine = Value
-}
-
-case class ParamWhoToFollowModuleDisplayTypeBuilder(
- displayTypeParam: Param[WhoToFollowModuleDisplayType.Value] =
- StaticParam(WhoToFollowModuleDisplayType.Vertical))
- extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleDisplayType = {
- val displayType = query.params(displayTypeParam)
- displayType match {
- case WhoToFollowModuleDisplayType.Carousel => Carousel
- case WhoToFollowModuleDisplayType.CompactCarousel => CompactCarousel
- case WhoToFollowModuleDisplayType.ConversationTree => ConversationTree
- case WhoToFollowModuleDisplayType.GridCarousel => GridCarousel
- case WhoToFollowModuleDisplayType.Vertical => Vertical
- case WhoToFollowModuleDisplayType.VerticalConversation => VerticalConversation
- case WhoToFollowModuleDisplayType.VerticalGrid => VerticalGrid
- case WhoToFollowModuleDisplayType.VerticalWithContextLine => VerticalWithContextLine
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala
deleted file mode 100644
index a7f9c647f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticModuleDisplayTypeBuilder(displayType: ModuleDisplayType)
- extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] {
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ModuleDisplayType = displayType
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala
deleted file mode 100644
index 38f1a7657..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-
-case class TimelineModuleBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- entryNamespace: EntryNamespace,
- displayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, Candidate],
- clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate],
- moduleIdGeneration: ModuleIdGeneration = AutomaticUniqueModuleId(),
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, Candidate]
- ] = None,
- headerBuilder: Option[BaseModuleHeaderBuilder[Query, Candidate]] = None,
- footerBuilder: Option[BaseModuleFooterBuilder[Query, Candidate]] = None,
- metadataBuilder: Option[BaseModuleMetadataBuilder[Query, Candidate]] = None,
- showMoreBehaviorBuilder: Option[BaseModuleShowMoreBehaviorBuilder[Query, Candidate]] = None)
- extends BaseTimelineModuleBuilder[Query, Candidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): TimelineModule = {
- val firstCandidate = candidates.head
- TimelineModule(
- id = moduleIdGeneration.moduleId,
- // Sort indexes are automatically set in the domain marshaller phase
- sortIndex = None,
- entryNamespace = entryNamespace,
- // Modules should not need an element by default; only items should
- clientEventInfo =
- clientEventInfoBuilder(query, firstCandidate.candidate, firstCandidate.features, None),
- feedbackActionInfo = feedbackActionInfoBuilder.flatMap(
- _.apply(query, firstCandidate.candidate, firstCandidate.features)),
- isPinned = None,
- // Items are automatically set in the domain marshaller phase
- items = Seq.empty,
- displayType = displayTypeBuilder(query, candidates),
- header = headerBuilder.flatMap(_.apply(query, candidates)),
- footer = footerBuilder.flatMap(_.apply(query, candidates)),
- metadata = metadataBuilder.map(_.apply(query, candidates)),
- showMoreBehavior = showMoreBehaviorBuilder.map(_.apply(query, candidates))
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD
deleted file mode 100644
index 56c339994..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/github/scopt",
- "util/util-core/src/main/java/com/twitter/io",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala
deleted file mode 100644
index 5c2a45856..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.twitter.product_mixer.component_library.experiments.metrics
-
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-
-object MetricDefinition {
- val SingleQuote = """""""
- val DoubleQuote = """"""""
-}
-
-/**
- * Base class for all metric definitions
- */
-sealed trait MetricDefinition {
- def toCsvField: Seq[String]
- val metricDefinitionType: String
-}
-
-/**
- * Pattern Metric Definition
- * @param pattern the regex pattern for this metric
- */
-case class NamedPatternMetricDefinition(
- pattern: Seq[String])
- extends MetricDefinition {
- override def toCsvField: Seq[String] = pattern
- override val metricDefinitionType: String = "NAMED_PATTERN"
-}
-
-/**
- * Strainer Metric Definition
- * @param strainerExpression a filter on top of client events
- */
-case class StrainerMetricDefinition(
- strainerExpression: String)
- extends MetricDefinition {
- import MetricDefinition._
- override def toCsvField: Seq[String] = {
- Seq(strainerExpression.replaceAll(SingleQuote, DoubleQuote))
- }
- override val metricDefinitionType: String = "STRAINER"
-}
-
-/**
- * Lambda Metric Definition
- * @param lambdaExpression a scala function mapping client events to a double
- */
-case class LambdaMetricDefinition(
- lambdaExpression: String)
- extends MetricDefinition {
- import MetricDefinition._
- override def toCsvField: Seq[String] = {
- Seq(lambdaExpression.replaceAll(SingleQuote, DoubleQuote))
- }
- override val metricDefinitionType: String = "LAMBDA"
-}
-
-case class BucketRatioMetricDefinition(
- numerator: String,
- denominator: String)
- extends MetricDefinition {
- override def toCsvField: Seq[String] = {
- Seq(s"(${numerator}) / (${denominator})")
- }
- override val metricDefinitionType: String = "BUCKET_RATIO"
-}
-
-object Metric {
- val bucketRatioPattern = "[(]+(.+)[)]+ / [(]+(.+)[)]+".r
-
- /**
- * Creates a new Metric given a template line.
- * @param line semicolon separated line string
- * ignore line with comment, represented by hashtag at the beginning of the line
- * @throws RuntimeException if the line is invalid
- */
- def fromLine(line: String): Metric = {
- val splits = line.split(";")
- // at least two parts separated by semicolon (third part is optional)
- if (splits.lengthCompare(2) >= 0) {
- val metricExpression = splits(0)
- val metricName = splits(1)
- val metricDefinition = Try(splits(2)) match {
- case Return("NAMED_PATTERN") => NamedPatternMetricDefinition(Seq(metricExpression))
- case Return("STRAINER") => StrainerMetricDefinition(metricExpression)
- case Return("LAMBDA") => LambdaMetricDefinition(metricExpression)
- case Return("BUCKET_RATIO") =>
- metricExpression match {
- case bucketRatioPattern(numerator, denominator) =>
- BucketRatioMetricDefinition(numerator, denominator)
- case _ =>
- throw new RuntimeException(
- s"Invalid metric definition for Bucket Ratio. Expected format (numerator)/(denominator) but found $metricExpression")
- }
- case Return(other) =>
- throw new RuntimeException(s"Invalid metric definition in line in template file: $line")
- // default to named pattern
- case Throw(_) => NamedPatternMetricDefinition(List(metricExpression))
- }
-
- Metric(metricName, metricDefinition)
- } else {
- throw new RuntimeException(s"Invalid line in template file: $line")
- }
- }
-}
-
-/**
- *
- * @param name globally unique metric name (current DDG limitation)
- * @param definition the metric definition for this metric
- */
-case class Metric(
- name: String,
- definition: MetricDefinition)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala
deleted file mode 100644
index ccd238cd8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.experiments.metrics
-
-import scala.collection.immutable.ListSet
-
-/**
- *
- * @param id optional metric group id. If id is None, this means the group
- * is being newly created and the id is not provisioned by go/ddg. Otherwise, the metric
- * group is present in DDG and has a corresponding id.
- * @param name metric group name
- * @param description metric group description
- * @param metrics set of metrics that belong to this metric group
- */
-case class MetricGroup(
- id: Option[Long],
- name: String,
- description: String,
- metrics: ListSet[Metric]) {
-
- /*
- * Returns a CSV representation of this metric group that can be imported via DDG's bulk import tool
- * The bulk import tool consumes CSV data with the following columns:
- * 1. group name
- * 2. group description
- * 3. metric name
- * 4. metric description
- * 5. metric pattern
- * 6. group id -- numeric id
- * 7. (optional) metric type -- `NAMED_PATTERN`, `STRAINER`, or `LAMBDA`.
- */
- def toCsv: String = {
- val metricCsvLines: ListSet[String] = for {
- metric <- metrics
- definition <- metric.definition.toCsvField
- } yield {
- Seq(
- name,
- description,
- metric.name,
- metric.name,
- // wrap in single quotes so that DDG bulk import tool correctly parses
- s""""$definition"""",
- id.map(_.toString).getOrElse(""),
- metric.definition.metricDefinitionType
- ).mkString(",")
- }
- println(s"Generated metrics in CSV count: ${metricCsvLines.size}")
- metricCsvLines.mkString("\n")
- }
-
- // Unique metric names based on globally unique metric name
- def uniqueMetricNames: Set[String] =
- metrics.groupBy(_.name).keys.toSet
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala
deleted file mode 100644
index b01af3cc2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.twitter.product_mixer.component_library.experiments.metrics
-
-import com.twitter.product_mixer.component_library.experiments.metrics.PlaceholderConfig.PlaceholdersMap
-import java.io.File
-import java.io.PrintWriter
-import scala.collection.immutable.ListSet
-import scala.io.Source
-import scopt.OptionParser
-
-private case class MetricTemplateCLIConfig(
- // default values required for OptionParser
- templateFileName: String = null,
- outputFileName: String = null,
- metricGroupName: String = null,
- metricGroupDesc: String = null,
- metricGroupId: Option[Long] = None,
- absolutePath: Option[String] = None)
-
-trait MetricTemplateCLIRunner {
- def templateDir: String
- def placeholders: PlaceholdersMap
- private val ProgramName = "Metric Template CLI"
- private val VersionNumber = "1.0"
-
- private def mkPath(fileName: String, absolutePath: Option[String]): String = {
- val relativeDir = s"$templateDir/$fileName"
- absolutePath match {
- case Some(path) => s"$path/$relativeDir"
- case _ => relativeDir
- }
- }
-
- def main(args: Array[String]): Unit = {
- val parser = new OptionParser[MetricTemplateCLIConfig](ProgramName) {
- head(ProgramName, VersionNumber)
- // option invoked by -o or --output
- opt[String]('o', "output")
- .required()
- .valueName("")
- .action((value, config) => config.copy(outputFileName = value))
- .text("output CSV file with interpolated lines")
- // option invoked by -t or --template
- opt[String]('t', "template")
- .required()
- .valueName("")
- .action((value, config) => config.copy(templateFileName = value))
- .text(
- s"input template file (see README.md for template format). Path is relative to $templateDir.")
- // option invoked by -n or --name
- opt[String]('n', "name")
- .required()
- .valueName("")
- .action((value, config) => config.copy(metricGroupName = value))
- .text("metric group name")
- // option invoked by -d or --description
- opt[String]('d', "description")
- .required()
- .valueName("")
- .action((value, config) => config.copy(metricGroupDesc = value))
- .text("metric group description")
- // option invoked by --id
- opt[Long]("id")
- .optional()
- .valueName("")
- .action((value, config) => config.copy(metricGroupId = Some(value)))
- .text("metric group ID (metric MUST be created in go/ddg)")
- // option invoked by -p or --path
- opt[String]('p', "path")
- .optional()
- .valueName("")
- .action((value, config) => config.copy(absolutePath = Some(value)))
- .text(s"absolute path pointing to the $templateDir. Required by bazel")
- }
-
- parser.parse(args, MetricTemplateCLIConfig()) match {
- case Some(config) =>
- val templateLines =
- Source.fromFile(mkPath(config.templateFileName, config.absolutePath)).getLines.toList
- val interpolatedLines = templateLines
- .filter(!_.startsWith("#")).flatMap(MetricTemplates.interpolate(_, placeholders))
- val writer = new PrintWriter(new File(mkPath(config.outputFileName, config.absolutePath)))
- val metrics = interpolatedLines.map(Metric.fromLine)
- println(s"${metrics.size} metric definitions found in template file.")
- val dupMetrics = metrics.groupBy(identity).collect {
- case (dup, lst) if lst.lengthCompare(1) > 0 => dup
- }
- println(s"\nWARNING: ${dupMetrics.size} Duplicate metric definition(s)\n$dupMetrics\n")
- val metricGroup = MetricGroup(
- config.metricGroupId,
- config.metricGroupName,
- config.metricGroupDesc,
- metrics.to[ListSet])
- println(s"${metricGroup.uniqueMetricNames.size} unique DDG metrics with " +
- s"${metricGroup.metrics.size} metric definitions in '${metricGroup.name}' metric group.")
- writer.write(metricGroup.toCsv)
- writer.close()
- case _ =>
- // arguments are bad, error message will have been displayed
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala
deleted file mode 100644
index 9640b1d8b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.twitter.product_mixer.component_library.experiments.metrics
-
-import com.twitter.product_mixer.component_library.experiments.metrics.PlaceholderConfig.PlaceholdersMap
-import reflect.ClassTag
-import scala.reflect.runtime.universe._
-import scala.util.matching.Regex
-
-case class MatchedPlaceholder(outerKey: String, innerKey: Option[String] = None)
-
-object MetricTemplates {
- // Matches "${placeholder}" where `placeholder` is in a matched group
- val PlaceholderPattern: Regex = "\\$\\{([^\\}]+)\\}".r.unanchored
- // Matches "${placeholder[index]}" where `placeholder` and `index` are in different matched groups
- val IndexedPlaceholderPattern: Regex = "\\$\\{([^\\[]+)\\[([^\\]]+)\\]\\}".r.unanchored
- val DefaultFieldName = "name"
-
- def interpolate(inputTemplate: String, placeholders: PlaceholdersMap): Seq[String] = {
- val matchedPlaceholders = getMatchedPlaceholders(inputTemplate)
- val groupedPlaceholders = matchedPlaceholders.groupBy(_.outerKey)
- val placeholderKeyValues = getPlaceholderKeyValues(groupedPlaceholders, placeholders)
- val (keys, values) = (placeholderKeyValues.map(_._1), placeholderKeyValues.map(_._2))
- val cross: Seq[List[Named]] = crossProduct(values)
- val mirror = runtimeMirror(getClass.getClassLoader) // necessary for reflection
- for {
- interpolatables <- cross
- } yield {
- assert(
- keys.length == interpolatables.length,
- s"Unexpected length mismatch between $keys and $interpolatables")
- var replacementStr = inputTemplate
- keys.zip(interpolatables).foreach {
- case (key, interpolatable) =>
- val accessors = caseAccessors(mirror, interpolatable)
- groupedPlaceholders(key).foreach { placeholder: MatchedPlaceholder =>
- val templateKey = generateTemplateKey(placeholder)
- val fieldName = placeholder.innerKey.getOrElse(DefaultFieldName)
- val fieldValue = getFieldValue(mirror, interpolatable, accessors, fieldName)
- replacementStr = replacementStr.replaceAll(templateKey, fieldValue)
- }
- }
- replacementStr
- }
- }
-
- def getMatchedPlaceholders(inputTemplate: String): Seq[MatchedPlaceholder] = {
- for {
- matched <- PlaceholderPattern.findAllIn(inputTemplate).toSeq
- } yield {
- val matchedWithIndexOpt = IndexedPlaceholderPattern.findFirstMatchIn(matched)
- val (outer, inner) = matchedWithIndexOpt
- .map { matchedWithIndex =>
- (matchedWithIndex.group(1), Some(matchedWithIndex.group(2)))
- }.getOrElse((matched, None))
- val outerKey = unwrap(outer)
- val innerKey = inner.map(unwrap(_))
- MatchedPlaceholder(outerKey, innerKey)
- }
- }
-
- def unwrap(str: String): String =
- str.stripPrefix("${").stripSuffix("}")
-
- def wrap(str: String): String =
- "\\$\\{" + str + "\\}"
-
- def getPlaceholderKeyValues(
- groupedPlaceholders: Map[String, Seq[MatchedPlaceholder]],
- placeholders: PlaceholdersMap
- ): Seq[(String, Seq[Named])] = {
- groupedPlaceholders.toSeq
- .map {
- case (outerKey, _) =>
- val placeholderValues = placeholders.getOrElse(
- outerKey,
- throw new RuntimeException(s"Failed to find values of $outerKey in placeholders"))
- outerKey -> placeholderValues
- }
- }
-
- def crossProduct[T](seqOfSeqOfItems: Seq[Seq[T]]): Seq[List[T]] = {
- if (seqOfSeqOfItems.isEmpty) {
- List(Nil)
- } else {
- for {
- // for every item in the head list
- item <- seqOfSeqOfItems.head
- // for every result (List) based on the cross-product of tail
- resultList <- crossProduct(seqOfSeqOfItems.tail)
- } yield {
- item :: resultList
- }
- }
- }
-
- def generateTemplateKey(matched: MatchedPlaceholder): String = {
- matched.innerKey match {
- case None => wrap(matched.outerKey)
- case Some(innerKeyString) => wrap(matched.outerKey + "\\[" + innerKeyString + "\\]")
- }
- }
-
- // Given an instance and a field name, use reflection to get its value.
- def getFieldValue[T: ClassTag](
- mirror: Mirror,
- cls: T,
- accessors: Map[String, MethodSymbol],
- fieldName: String
- ): String = {
- val instance: InstanceMirror = mirror.reflect(cls)
- val accessor = accessors.getOrElse(
- fieldName,
- throw new RuntimeException(s"Failed to find value of $fieldName for $cls"))
- instance.reflectField(accessor).get.toString // .get is safe due to check above
- }
-
- // Given an instance, use reflection to get a mapping for field name -> symbol
- def caseAccessors[T: ClassTag](mirror: Mirror, cls: T): Map[String, MethodSymbol] = {
- val classSymbol = mirror.classSymbol(cls.getClass)
- classSymbol.toType.members.collect {
- case m: MethodSymbol if m.isCaseAccessor => (m.name.toString -> m)
- }.toMap
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala
deleted file mode 100644
index 5a81073cc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.experiments.metrics
-
-// Base trait for all placeholder values
-sealed trait Named {
- def name: String
-}
-
-case class Const(override val name: String) extends Named
-
-// contains only client event patterns
-case class CEPattern(
- override val name: String,
- client: String = "",
- page: String = "",
- section: String = "",
- component: String = "",
- element: String = "",
- action: String = "",
- strainer: String = "")
- extends Named {
-
- override def toString: String = {
- "\"" + client + ":" + page + ":" + section + ":" + component + ":" + element + ":" + action + "\""
- }
-
-}
-
-case class Topic(
- override val name: String,
- topicId: String = "")
- extends Named
-
-object PlaceholderConfig {
- type PlaceholderKey = String
- type Placeholder = Seq[Named]
- type PlaceholdersMap = Map[PlaceholderKey, Placeholder]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD
deleted file mode 100644
index 7da3b156c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala
deleted file mode 100644
index 299d9515f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.UserId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import scala.reflect.ClassTag
-object FeatureStoreV1QueryUserIdFeature {
- def apply[Query <: PipelineQuery, Value](
- feature: FSv1Feature[UserId, Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1Feature[Query, Query, _ <: EntityId, Value]
- with FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value] =
- FeatureStoreV1QueryFeature(feature, QueryUserIdEntity, legacyName, defaultValue, enabledParam)
-}
-
-object FeatureStoreV1QueryUserIdAggregateFeature {
- def apply[Query <: PipelineQuery](
- featureGroup: TimelinesAggregationFrameworkFeatureGroup[UserId],
- enabledParam: Option[FSParam[Boolean]] = None,
- keepLegacyNames: Boolean = false,
- featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId] =
- FeatureStoreV1QueryFeatureGroup(
- featureGroup,
- QueryUserIdEntity,
- enabledParam,
- keepLegacyNames,
- featureNameTransform)((implicitly[ClassTag[UserId]]))
-}
-
-object QueryUserIdEntity extends FeatureStoreV1QueryEntity[PipelineQuery, UserId] {
- override val entity: Entity[UserId] = entities.core.User
-
- override def entityWithId(query: PipelineQuery): EntityWithId[UserId] =
- entity.withId(UserId(query.getUserIdLoggedOutSupport))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala
deleted file mode 100644
index bd026c60d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EdgeEntityId
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.UserId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import scala.reflect.ClassTag
-
-object FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature {
- def apply[Query <: PipelineQuery, Value](
- feature: FSv1Feature[EdgeEntityId[UserId, UserId], Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, TweetCandidate, _ <: EntityId, Value] =
- FeatureStoreV1CandidateFeature(
- feature,
- QueryUserIdTweetCandidateAuthorIdEntity,
- legacyName,
- defaultValue,
- enabledParam)
-}
-
-object FeatureStoreV1QueryUserIdTweetCandidateAuthorIdAggregateFeature {
- def apply[Query <: PipelineQuery](
- featureGroup: TimelinesAggregationFrameworkFeatureGroup[EdgeEntityId[UserId, UserId]],
- enabledParam: Option[FSParam[Boolean]] = None,
- keepLegacyNames: Boolean = false,
- featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] =
- FeatureStoreV1CandidateFeatureGroup(
- featureGroup,
- QueryUserIdTweetCandidateAuthorIdEntity,
- enabledParam,
- keepLegacyNames,
- featureNameTransform
- )(implicitly[ClassTag[EdgeEntityId[UserId, UserId]]])
-}
-
-object QueryUserIdTweetCandidateAuthorIdEntity
- extends FeatureStoreV1CandidateEntity[
- PipelineQuery,
- TweetCandidate,
- EdgeEntityId[UserId, UserId]
- ] {
- override val entity: Entity[EdgeEntityId[UserId, UserId]] = entities.core.UserAuthor
-
- override def entityWithId(
- query: PipelineQuery,
- tweet: TweetCandidate,
- existingFeatures: FeatureMap
- ): EntityWithId[EdgeEntityId[UserId, UserId]] =
- entity.withId(
- EdgeEntityId(
- UserId(query.getUserIdLoggedOutSupport),
- UserId(existingFeatures.get(TweetAuthorIdFeature))))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala
deleted file mode 100644
index 9031e88be..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EdgeEntityId
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.TweetId
-import com.twitter.ml.featurestore.lib.UserId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import scala.reflect.ClassTag
-
-object FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature {
- def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate, Value](
- feature: FSv1Feature[EdgeEntityId[UserId, TweetId], Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] =
- FeatureStoreV1CandidateFeature(
- feature,
- QueryUserIdTweetCandidateTweetIdEntity,
- legacyName,
- defaultValue,
- enabledParam)
-}
-
-object FeatureStoreV1QueryUserIdTweetCandidateTweetIdAggregateFeature {
- def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate](
- featureGroup: TimelinesAggregationFrameworkFeatureGroup[EdgeEntityId[UserId, TweetId]],
- enabledParam: Option[FSParam[Boolean]] = None,
- keepLegacyNames: Boolean = false,
- featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] =
- FeatureStoreV1CandidateFeatureGroup(
- featureGroup,
- QueryUserIdTweetCandidateTweetIdEntity,
- enabledParam,
- keepLegacyNames,
- featureNameTransform
- )(implicitly[ClassTag[EdgeEntityId[UserId, TweetId]]])
-}
-
-object QueryUserIdTweetCandidateTweetIdEntity
- extends FeatureStoreV1CandidateEntity[
- PipelineQuery,
- BaseTweetCandidate,
- EdgeEntityId[UserId, TweetId]
- ] {
- override val entity: Entity[EdgeEntityId[UserId, TweetId]] = entities.core.UserTweet
-
- override def entityWithId(
- query: PipelineQuery,
- tweet: BaseTweetCandidate,
- existingFeatures: FeatureMap
- ): EntityWithId[EdgeEntityId[UserId, TweetId]] =
- entity.withId(EdgeEntityId(UserId(query.getUserIdLoggedOutSupport), TweetId(tweet.id)))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala
deleted file mode 100644
index b78c9569a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.UserId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import scala.reflect.ClassTag
-
-object FeatureStoreV1TweetCandidateAuthorIdFeature {
- def apply[Query <: PipelineQuery, Value](
- feature: FSv1Feature[UserId, Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, TweetCandidate, _ <: EntityId, Value] =
- FeatureStoreV1CandidateFeature(
- feature,
- TweetCandidateAuthorIdEntity,
- legacyName,
- defaultValue,
- enabledParam)
-}
-
-object FeatureStoreV1TweetCandidateAuthorIdAggregateFeature {
- def apply[Query <: PipelineQuery](
- featureGroup: TimelinesAggregationFrameworkFeatureGroup[UserId],
- enabledParam: Option[FSParam[Boolean]] = None,
- keepLegacyNames: Boolean = false,
- featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] =
- FeatureStoreV1CandidateFeatureGroup(
- featureGroup,
- TweetCandidateAuthorIdEntity,
- enabledParam,
- keepLegacyNames,
- featureNameTransform
- )(implicitly[ClassTag[UserId]])
-}
-
-object TweetCandidateAuthorIdEntity
- extends FeatureStoreV1CandidateEntity[PipelineQuery, TweetCandidate, UserId] {
- override val entity: Entity[UserId] = entities.core.Author
-
- override def entityWithId(
- query: PipelineQuery,
- tweet: TweetCandidate,
- existingFeatures: FeatureMap
- ): EntityWithId[UserId] =
- entity.withId(UserId(existingFeatures.get(TweetAuthorIdFeature)))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala
deleted file mode 100644
index c75bf21ac..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.TweetId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-
-object FeatureStoreV1TweetCandidateTweetIdFeature {
- def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate, Value](
- feature: FSv1Feature[TweetId, Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] =
- FeatureStoreV1CandidateFeature(
- feature,
- TweetCandidateTweetIdEntity,
- legacyName,
- defaultValue,
- enabledParam)
-}
-
-object FeatureStoreV1TweetCandidateTweetIdAggregateFeature {
- def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate](
- featureGroup: TimelinesAggregationFrameworkFeatureGroup[TweetId],
- enabledParam: Option[FSParam[Boolean]] = None,
- keepLegacyNames: Boolean = false,
- featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId] =
- FeatureStoreV1CandidateFeatureGroup(
- featureGroup,
- TweetCandidateTweetIdEntity,
- enabledParam,
- keepLegacyNames,
- featureNameTransform
- )
-}
-
-object TweetCandidateTweetIdEntity
- extends FeatureStoreV1CandidateEntity[PipelineQuery, BaseTweetCandidate, TweetId] {
- override val entity: Entity[TweetId] = entities.core.Tweet
-
- override def entityWithId(
- query: PipelineQuery,
- tweet: BaseTweetCandidate,
- existingFeatures: FeatureMap
- ): EntityWithId[TweetId] =
- entity.withId(TweetId(tweet.id))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala
deleted file mode 100644
index a0947b995..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.feature.featurestorev1
-
-import com.twitter.ml.featurestore.catalog.entities
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.UserId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-
-object FeatureStoreV1UserCandidateUserIdFeature {
- def apply[Query <: PipelineQuery, Candidate <: BaseUserCandidate, Value](
- feature: FSv1Feature[UserId, Value],
- legacyName: Option[String] = None,
- defaultValue: Option[Value] = None,
- enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] =
- FeatureStoreV1CandidateFeature(
- feature,
- UserCandidateUserIdEntity,
- legacyName,
- defaultValue,
- enabledParam)
-}
-
-object UserCandidateUserIdEntity
- extends FeatureStoreV1CandidateEntity[PipelineQuery, BaseUserCandidate, UserId] {
- override val entity: Entity[UserId] = entities.core.User
-
- override def entityWithId(
- query: PipelineQuery,
- user: BaseUserCandidate,
- existingFeatures: FeatureMap
- ): EntityWithId[UserId] =
- entity.withId(UserId(user.id))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD
deleted file mode 100644
index 78840577d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala
deleted file mode 100644
index 107f04fff..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ad}
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.storehaus.ReadableStore
-import com.twitter.util.Future
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object AdvertiserBrandSafetySettingsFeature
- extends FeatureWithDefaultOnFailure[AdsCandidate, Option[ad.AdvertiserBrandSafetySettings]] {
- override val defaultValue = None
-}
-
-@Singleton
-case class AdvertiserBrandSafetySettingsFeatureHydrator[
- Query <: PipelineQuery with AdsQuery,
- Candidate <: AdsCandidate] @Inject() (
- advertiserBrandSafetySettingsStore: ReadableStore[Long, ad.AdvertiserBrandSafetySettings])
- extends CandidateFeatureHydrator[Query, Candidate] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "AdvertiserBrandSafetySettings")
-
- override val features: Set[Feature[_, _]] = Set(AdvertiserBrandSafetySettingsFeature)
-
- override def apply(
- query: Query,
- candidate: Candidate,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = {
-
- val featureMapFuture: Future[FeatureMap] = advertiserBrandSafetySettingsStore
- .get(candidate.adImpression.advertiserId)
- .map { advertiserBrandSafetySettingsOpt =>
- FeatureMapBuilder()
- .add(AdvertiserBrandSafetySettingsFeature, advertiserBrandSafetySettingsOpt).build()
- }
-
- Stitch.callFuture(featureMapFuture)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD
deleted file mode 100644
index 4c66c4346..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/twitter/storehaus:core",
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "src/thrift/com/twitter/ads/adserver:ads_shared_types-scala",
- ],
- exports = [
- "3rdparty/jvm/com/twitter/storehaus:core",
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "src/thrift/com/twitter/ads/adserver:ads_shared_types-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel
deleted file mode 100644
index 3759377bd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "snowflake/src/main/scala/com/twitter/snowflake/id",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala
deleted file mode 100644
index 4f0d99e82..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.decay
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.snowflake.id.SnowflakeId
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-import com.twitter.util.Duration
-
-object DecayScore extends Feature[UniversalNoun[Long], Double]
-
-/**
- * Hydrates snowflake ID candidates with a decay score:
- *
- * It is using exponential decay formula to calculate the score
- * exp(k * age)
- * where k = ln(0.5) / half-life
- *
- * Here is an example for half-life = 1 day
- * For the brand new tweet it will be exp((ln(0.5)/1)*0) = 1
- * For the tweet which was created 1 day ago it will be exp((ln(0.5)/1)*1) = 0.5
- * For the tweet which was created 10 day ago it will be exp((ln(0.5)/1)*10) = 0.00097
- *
- * Reference: https://www.cuemath.com/exponential-decay-formula/
- *
- * @note This penalizes but does not filter out the candidate, so "stale" candidates can still appear.
- */
-case class DecayCandidateFeatureHydrator[Candidate <: UniversalNoun[Long]](
- halfLife: Param[Duration] = StaticParam[Duration](2.days),
- resultFeature: Feature[UniversalNoun[Long], Double] = DecayScore)
- extends CandidateFeatureHydrator[PipelineQuery, Candidate] {
-
- override val features: Set[Feature[_, _]] = Set(resultFeature)
-
- override val identifier: FeatureHydratorIdentifier =
- FeatureHydratorIdentifier("Decay")
-
- override def apply(
- query: PipelineQuery,
- candidate: Candidate,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = {
- val halfLifeInMillis = query.params(halfLife).inMillis
-
- val creationTime = SnowflakeId.timeFromId(candidate.id)
- val ageInMillis = creationTime.untilNow.inMilliseconds
-
- // it is using a exponential decay formula: e^(k * tweetAge)
- // where k = ln(0.5) / half-life
- val k = math.log(0.5D) / halfLifeInMillis
- val decayScore = math.exp(k * ageInMillis)
-
- Stitch.value(
- FeatureMapBuilder()
- .add(resultFeature, decayScore)
- .build())
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD
deleted file mode 100644
index a9e2c7cc4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala
deleted file mode 100644
index 621eed2e9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated
-
-import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedBulkCandidateFeatureHydrator.IdentifierPrefix
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[BulkCandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[BulkCandidateFeatureHydrator]] on and off
- * @param bulkCandidateFeatureHydrator the underlying [[BulkCandidateFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class ParamGatedBulkCandidateFeatureHydrator[
- -Query <: PipelineQuery,
- Result <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- bulkCandidateFeatureHydrator: BulkCandidateFeatureHydrator[Query, Result])
- extends BulkCandidateFeatureHydrator[Query, Result]
- with Conditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- IdentifierPrefix + bulkCandidateFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = bulkCandidateFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = bulkCandidateFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, bulkCandidateFeatureHydrator, query.params(enabledParam))
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Result]]
- ): Stitch[Seq[FeatureMap]] = bulkCandidateFeatureHydrator(query, candidates)
-}
-
-object ParamGatedBulkCandidateFeatureHydrator {
- val IdentifierPrefix = "ParamGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala
deleted file mode 100644
index 6409145e5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated
-
-import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedCandidateFeatureHydrator.IdentifierPrefix
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[CandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[CandidateFeatureHydrator]] on and off
- * @param candidateFeatureHydrator the underlying [[CandidateFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class ParamGatedCandidateFeatureHydrator[
- -Query <: PipelineQuery,
- -Result <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- candidateFeatureHydrator: CandidateFeatureHydrator[Query, Result])
- extends CandidateFeatureHydrator[Query, Result]
- with Conditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- IdentifierPrefix + candidateFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = candidateFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, candidateFeatureHydrator, query.params(enabledParam))
-
- override def apply(
- query: Query,
- candidate: Result,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = candidateFeatureHydrator.apply(query, candidate, existingFeatures)
-}
-
-object ParamGatedCandidateFeatureHydrator {
- val IdentifierPrefix = "ParamGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD
deleted file mode 100644
index 7b18d7b06..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala
deleted file mode 100644
index d151c4374..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.featurestorev1.ParamGatedFeatureStoreV1CandidateFeatureHydrator.IdentifierPrefix
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[FeatureStoreV1CandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[FeatureStoreV1CandidateFeatureHydrator]] on and off
- * @param candidateFeatureHydrator the underlying [[FeatureStoreV1CandidateFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Candidate The type of the candidates
- */
-case class ParamGatedFeatureStoreV1CandidateFeatureHydrator[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- candidateFeatureHydrator: FeatureStoreV1CandidateFeatureHydrator[Query, Candidate])
- extends FeatureStoreV1CandidateFeatureHydrator[Query, Candidate]
- with Conditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- IdentifierPrefix + candidateFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts
-
- override val features: Set[
- BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _]
- ] = candidateFeatureHydrator.features
-
- override val clientBuilder: FeatureStoreV1DynamicClientBuilder =
- candidateFeatureHydrator.clientBuilder
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, candidateFeatureHydrator, query.params(enabledParam))
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = candidateFeatureHydrator(query, candidates)
-}
-
-object ParamGatedFeatureStoreV1CandidateFeatureHydrator {
- val IdentifierPrefix = "ParamGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel
deleted file mode 100644
index 579f420ee..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala
deleted file mode 100644
index e9d74826c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.qualityfactor_gated
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-object QualityFactorGatedCandidateFeatureHydrator {
- val IdentifierPrefix = "QfGated"
-}
-
-/**
- * A [[CandidateFeatureHydrator]] with [[Conditionally]] based on a qualityFactor threshold.
- * @param pipelineIdentifier identifier of the pipeline that associated with observed quality factor
- * @param qualityFactorInclusiveThreshold the inclusive threshold of quality factor that value below it results in
- * the underlying hydrator being turned off
- * @param candidateFeatureHydrator the underlying [[CandidateFeatureHydrator]] to run when quality factor value
- * is above the given inclusive threshold
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class QualityFactorGatedCandidateFeatureHydrator[
- -Query <: PipelineQuery with HasQualityFactorStatus,
- Result <: UniversalNoun[Any]
-](
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorInclusiveThreshold: Param[Double],
- candidateFeatureHydrator: CandidateFeatureHydrator[Query, Result])
- extends CandidateFeatureHydrator[Query, Result]
- with Conditionally[Query] {
- import QualityFactorGatedCandidateFeatureHydrator._
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- IdentifierPrefix + candidateFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = candidateFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean = Conditionally.and(
- query,
- candidateFeatureHydrator,
- query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params(
- qualityFactorInclusiveThreshold))
-
- override def apply(
- query: Query,
- candidate: Result,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = candidateFeatureHydrator.apply(query, candidate, existingFeatures)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD
deleted file mode 100644
index 3a2b817bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala
deleted file mode 100644
index 651f0f4b0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_is_nsfw
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient}
-import com.twitter.tweetypie.{thriftscala => t}
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-import com.twitter.util.logging.Logging
-
-// The VF NsfwHighPrecisionLabel that powers the NSFW determination here has been deprecated and is no longer written to.
-@deprecated("Prefer VisibilityReason")
-object IsNsfw extends FeatureWithDefaultOnFailure[TweetCandidate, Option[Boolean]] {
-
- /**
- * Generic Logic to evaluate whether a tweet is nsfw
- * @param hasNsfwHighPrecisionLabel flag for tweetypieTweet nsfwHighPrecision label
- * @param isNsfwUser flag for tweetypieTweet coreData nsfwUser flag
- * @param isNsfwAdmin flag for tweetypieTweet coreData nsfwAdmin flag
- * @return isNsfw to true if any of the three flags is true
- */
- def apply(
- hasNsfwHighPrecisionLabel: Option[Boolean],
- isNsfwUser: Option[Boolean],
- isNsfwAdmin: Option[Boolean]
- ): Boolean = {
- hasNsfwHighPrecisionLabel
- .getOrElse(false) || (isNsfwUser.getOrElse(false) || isNsfwAdmin.getOrElse(false))
- }
-
- override val defaultValue = None
-}
-
-// The VF NsfwHighPrecisionLabel that powers the NSFW determination here has been deprecated and is no longer written to.
-// TODO: Remove after all dependencies have migrated to using TweetCandidateVisibilityReasonFeatureHydrator.
-@deprecated("Prefer TweetCandidateVisibilityReasonFeatureHydrator")
-case class TweetIsNsfwCandidateFeatureHydrator(
- tweetypieStitchClient: TweetypieStitchClient,
- tweetVisibilityPolicy: t.TweetVisibilityPolicy)
- extends BulkCandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate]
- with Logging {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("TweetIsNsfw")
-
- override def features: Set[Feature[_, _]] = Set(IsNsfw)
-
- private val NsfwLabelFields: Set[t.TweetInclude] = Set[t.TweetInclude](
- // Tweet fields containing NSFW related attributes, in addition to what exists in coreData.
- t.TweetInclude.TweetFieldId(t.Tweet.NsfwHighPrecisionLabelField.id),
- t.TweetInclude.TweetFieldId(t.Tweet.CoreDataField.id)
- )
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[BaseTweetCandidate]]
- ): Stitch[Seq[FeatureMap]] = {
- Stitch
- .traverse(candidates.map(_.candidate.id)) { tweetId =>
- tweetypieStitchClient
- .getTweetFields(
- tweetId = tweetId,
- options = t.GetTweetFieldsOptions(
- forUserId = query.getOptionalUserId,
- tweetIncludes = NsfwLabelFields,
- doNotCache = true,
- visibilityPolicy = tweetVisibilityPolicy,
- safetyLevel = None,
- )
- ).liftToTry
- }.map { getTweetFieldsResults: Seq[Try[t.GetTweetFieldsResult]] =>
- val tweets: Seq[Try[t.Tweet]] = getTweetFieldsResults.map {
- case Return(t.GetTweetFieldsResult(_, t.TweetFieldsResultState.Found(found), _, _)) =>
- Return(found.tweet)
- case Return(t.GetTweetFieldsResult(_, resultState, _, _)) =>
- Throw(IsNsfwFeatureHydrationFailure(s"Unexpected tweet result state: ${resultState}"))
- case Throw(e) =>
- Throw(e)
- }
-
- candidates.zip(tweets).map {
- case (candidateWithFeatures, tweetTry) =>
- val isNsfwFeature = tweetTry.map { tweet =>
- IsNsfw(
- hasNsfwHighPrecisionLabel = Some(tweet.nsfwHighPrecisionLabel.isDefined),
- isNsfwUser = tweet.coreData.map(_.nsfwUser),
- isNsfwAdmin = tweet.coreData.map(_.nsfwAdmin)
- )
- }
-
- FeatureMapBuilder()
- .add(IsNsfw, isNsfwFeature.map(Some(_)))
- .build()
- }
- }
- }
-}
-
-case class IsNsfwFeatureHydrationFailure(message: String)
- extends Exception(s"IsNsfwFeatureHydrationFailure(${message})")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel
deleted file mode 100644
index 9d9d9a421..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel
+++ /dev/null
@@ -1,42 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-strato",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-strato",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "stitch/stitch-core",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala
deleted file mode 100644
index ee985d9c4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx
-
-import com.twitter.ml.featurestore.timelines.thriftscala.TimelineScorerScoreView
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.component_library.scorer.tweet_tlx.TLXScore
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.strato.generated.client.ml.featureStore.TimelineScorerTweetScoresV1ClientColumn
-import com.twitter.timelinescorer.thriftscala.v1
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Hydrate Tweet Scores via Timeline Scorer (TLX)
- *
- * Note that this is the [[CandidateFeatureHydrator]] version of
- * [[com.twitter.product_mixer.component_library.scorer.tweet_tlx.TweetTLXStratoScorer]]
- */
-@Singleton
-class TweetTLXScoreCandidateFeatureHydrator @Inject() (
- column: TimelineScorerTweetScoresV1ClientColumn)
- extends CandidateFeatureHydrator[PipelineQuery, TweetCandidate] {
-
- override val identifier: FeatureHydratorIdentifier =
- FeatureHydratorIdentifier("TweetTLXScore")
-
- override val features: Set[Feature[_, _]] = Set(TLXScore)
-
- private val NoScoreMap = FeatureMapBuilder()
- .add(TLXScore, None)
- .build()
-
- override def apply(
- query: PipelineQuery,
- candidate: TweetCandidate,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = {
- query.getOptionalUserId match {
- case Some(userId) =>
- column.fetcher
- .fetch(candidate.id, TimelineScorerScoreView(Some(userId)))
- .map(scoredTweet =>
- scoredTweet.v match {
- case Some(v1.ScoredTweet(Some(_), score, _, _)) =>
- FeatureMapBuilder()
- .add(TLXScore, score)
- .build()
- case _ => throw new Exception(s"Invalid response from TLX: ${scoredTweet.v}")
- })
- case _ =>
- Stitch.value(NoScoreMap)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD
deleted file mode 100644
index 298c869f3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD
+++ /dev/null
@@ -1,29 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala
deleted file mode 100644
index 5f20598b5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tweetypie
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.spam.rtf.thriftscala.SafetyLevel
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient}
-import com.twitter.tweetypie.thriftscala.TweetVisibilityPolicy
-import com.twitter.tweetypie.{thriftscala => TP}
-
-// Candidate Features
-object IsCommunityTweetFeature extends Feature[TweetCandidate, Boolean]
-
-// Tweetypie VF Features
-object HasTakedownFeature extends Feature[TweetCandidate, Boolean]
-object HasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean]
-object IsHydratedFeature extends Feature[TweetCandidate, Boolean]
-object IsNarrowcastFeature extends Feature[TweetCandidate, Boolean]
-object IsNsfwAdminFeature extends Feature[TweetCandidate, Boolean]
-object IsNsfwFeature extends Feature[TweetCandidate, Boolean]
-object IsNsfwUserFeature extends Feature[TweetCandidate, Boolean]
-object IsNullcastFeature extends Feature[TweetCandidate, Boolean]
-object QuotedTweetDroppedFeature extends Feature[TweetCandidate, Boolean]
-object QuotedTweetHasTakedownFeature extends Feature[TweetCandidate, Boolean]
-object QuotedTweetHasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean]
-object QuotedTweetIdFeature extends Feature[TweetCandidate, Option[Long]]
-object SourceTweetHasTakedownFeature extends Feature[TweetCandidate, Boolean]
-object SourceTweetHasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean]
-object TakedownCountryCodesFeature extends Feature[TweetCandidate, Set[String]]
-object IsReplyFeature extends Feature[TweetCandidate, Boolean]
-object InReplyToFeature extends Feature[TweetCandidate, Option[Long]]
-object IsRetweetFeature extends Feature[TweetCandidate, Boolean]
-
-object TweetTweetypieCandidateFeatureHydrator {
- val CoreTweetFields: Set[TP.TweetInclude] = Set[TP.TweetInclude](
- TP.TweetInclude.TweetFieldId(TP.Tweet.IdField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.CoreDataField.id)
- )
-
- val NsfwLabelFields: Set[TP.TweetInclude] = Set[TP.TweetInclude](
- // Tweet fields containing NSFW related attributes, in addition to what exists in coreData.
- TP.TweetInclude.TweetFieldId(TP.Tweet.NsfwHighRecallLabelField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.NsfwHighPrecisionLabelField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.NsfaHighRecallLabelField.id)
- )
-
- val SafetyLabelFields: Set[TP.TweetInclude] = Set[TP.TweetInclude](
- // Tweet fields containing RTF labels for abuse and spam.
- TP.TweetInclude.TweetFieldId(TP.Tweet.SpamLabelField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.AbusiveLabelField.id)
- )
-
- val OrganicTweetTPHydrationFields: Set[TP.TweetInclude] = CoreTweetFields ++
- NsfwLabelFields ++
- SafetyLabelFields ++
- Set(
- TP.TweetInclude.TweetFieldId(TP.Tweet.TakedownCountryCodesField.id),
- // QTs imply a TweetyPie -> SGS request dependency
- TP.TweetInclude.TweetFieldId(TP.Tweet.QuotedTweetField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.EscherbirdEntityAnnotationsField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.CommunitiesField.id),
- // Field required for determining if a Tweet was created via News Camera.
- TP.TweetInclude.TweetFieldId(TP.Tweet.ComposerSourceField.id)
- )
-
- val InjectedTweetTPHydrationFields: Set[TP.TweetInclude] =
- OrganicTweetTPHydrationFields ++ Set(
- // Mentions imply a TweetyPie -> Gizmoduck request dependency
- TP.TweetInclude.TweetFieldId(TP.Tweet.MentionsField.id),
- TP.TweetInclude.TweetFieldId(TP.Tweet.HashtagsField.id)
- )
-
- val DefaultFeatureMap = FeatureMapBuilder()
- .add(IsNsfwAdminFeature, false)
- .add(IsNsfwUserFeature, false)
- .add(IsNsfwFeature, false)
- .add(IsNullcastFeature, false)
- .add(IsNarrowcastFeature, false)
- .add(HasTakedownFeature, false)
- .add(IsCommunityTweetFeature, false)
- .add(TakedownCountryCodesFeature, Set.empty: Set[String])
- .add(IsHydratedFeature, false)
- .add(HasTakedownForLocaleFeature, false)
- .add(QuotedTweetDroppedFeature, false)
- .add(SourceTweetHasTakedownFeature, false)
- .add(QuotedTweetHasTakedownFeature, false)
- .add(SourceTweetHasTakedownForLocaleFeature, false)
- .add(QuotedTweetHasTakedownForLocaleFeature, false)
- .add(IsReplyFeature, false)
- .add(InReplyToFeature, None)
- .add(IsRetweetFeature, false)
- .build()
-}
-
-class TweetTweetypieCandidateFeatureHydrator(
- tweetypieStitchClient: TweetypieStitchClient,
- safetyLevelPredicate: PipelineQuery => SafetyLevel)
- extends CandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate] {
-
- import TweetTweetypieCandidateFeatureHydrator._
-
- override val features: Set[Feature[_, _]] =
- Set(
- IsNsfwFeature,
- IsNsfwAdminFeature,
- IsNsfwUserFeature,
- IsNullcastFeature,
- IsNarrowcastFeature,
- HasTakedownFeature,
- IsCommunityTweetFeature,
- TakedownCountryCodesFeature,
- IsHydratedFeature,
- HasTakedownForLocaleFeature,
- QuotedTweetDroppedFeature,
- SourceTweetHasTakedownFeature,
- QuotedTweetHasTakedownFeature,
- SourceTweetHasTakedownForLocaleFeature,
- QuotedTweetHasTakedownForLocaleFeature,
- IsReplyFeature,
- InReplyToFeature,
- IsRetweetFeature
- )
-
- override val identifier: FeatureHydratorIdentifier =
- FeatureHydratorIdentifier("TweetTweetypie")
-
- override def apply(
- query: PipelineQuery,
- candidate: BaseTweetCandidate,
- existingFeatures: FeatureMap
- ): Stitch[FeatureMap] = {
- val countryCode = query.getCountryCode.getOrElse("")
-
- tweetypieStitchClient
- .getTweetFields(
- tweetId = candidate.id,
- options = TP.GetTweetFieldsOptions(
- tweetIncludes = OrganicTweetTPHydrationFields,
- includeRetweetedTweet = true,
- includeQuotedTweet = true,
- visibilityPolicy = TweetVisibilityPolicy.UserVisible,
- safetyLevel = Some(safetyLevelPredicate(query))
- )
- ).map {
- case TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), quoteOpt, _) =>
- val coreData = found.tweet.coreData
- val isNsfwAdmin = coreData.exists(_.nsfwAdmin)
- val isNsfwUser = coreData.exists(_.nsfwUser)
- val hasTakedown = coreData.exists(_.hasTakedown)
- val isReply = coreData.exists(_.reply.nonEmpty)
- val ancestorId = coreData.flatMap(_.reply).flatMap(_.inReplyToStatusId)
- val isRetweet = coreData.exists(_.share.nonEmpty)
- val takedownCountryCodes =
- found.tweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet
-
- val quotedTweetDropped = quoteOpt.exists {
- case _: TP.TweetFieldsResultState.Filtered =>
- true
- case _: TP.TweetFieldsResultState.NotFound =>
- true
- case _ => false
- }
- val quotedTweetIsNsfw = quoteOpt.exists {
- case quoteTweet: TP.TweetFieldsResultState.Found =>
- quoteTweet.found.tweet.coreData.exists(data => data.nsfwAdmin || data.nsfwUser)
- case _ => false
- }
- val quotedTweetHasTakedown = quoteOpt.exists {
- case quoteTweet: TP.TweetFieldsResultState.Found =>
- quoteTweet.found.tweet.coreData.exists(_.hasTakedown)
- case _ => false
- }
- val quotedTweetTakedownCountryCodes = quoteOpt
- .collect {
- case quoteTweet: TP.TweetFieldsResultState.Found =>
- quoteTweet.found.tweet.takedownCountryCodes
- .getOrElse(Seq.empty).map(_.toLowerCase).toSet
- }.getOrElse(Set.empty[String])
-
- val sourceTweetIsNsfw =
- found.retweetedTweet.exists(_.coreData.exists(data => data.nsfwAdmin || data.nsfwUser))
- val sourceTweetHasTakedown =
- found.retweetedTweet.exists(_.coreData.exists(_.hasTakedown))
- val sourceTweetTakedownCountryCodes = found.retweetedTweet
- .map { sourceTweet: TP.Tweet =>
- sourceTweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet
- }.getOrElse(Set.empty)
-
- FeatureMapBuilder()
- .add(IsNsfwAdminFeature, isNsfwAdmin)
- .add(IsNsfwUserFeature, isNsfwUser)
- .add(IsNsfwFeature, isNsfwAdmin || isNsfwUser || sourceTweetIsNsfw || quotedTweetIsNsfw)
- .add(IsNullcastFeature, coreData.exists(_.nullcast))
- .add(IsNarrowcastFeature, coreData.exists(_.narrowcast.nonEmpty))
- .add(HasTakedownFeature, hasTakedown)
- .add(
- HasTakedownForLocaleFeature,
- hasTakedownForLocale(hasTakedown, countryCode, takedownCountryCodes))
- .add(QuotedTweetDroppedFeature, quotedTweetDropped)
- .add(SourceTweetHasTakedownFeature, sourceTweetHasTakedown)
- .add(QuotedTweetHasTakedownFeature, quotedTweetHasTakedown)
- .add(
- SourceTweetHasTakedownForLocaleFeature,
- hasTakedownForLocale(
- sourceTweetHasTakedown,
- countryCode,
- sourceTweetTakedownCountryCodes))
- .add(
- QuotedTweetHasTakedownForLocaleFeature,
- hasTakedownForLocale(
- quotedTweetHasTakedown,
- countryCode,
- quotedTweetTakedownCountryCodes))
- .add(IsCommunityTweetFeature, found.tweet.communities.exists(_.communityIds.nonEmpty))
- .add(
- TakedownCountryCodesFeature,
- found.tweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet)
- .add(IsHydratedFeature, true)
- .add(IsReplyFeature, isReply)
- .add(InReplyToFeature, ancestorId)
- .add(IsRetweetFeature, isRetweet)
- .build()
-
- // If no tweet result found, return default features
- case _ =>
- DefaultFeatureMap
- }
- }
-
- private def hasTakedownForLocale(
- hasTakedown: Boolean,
- countryCode: String,
- takedownCountryCodes: Set[String]
- ) = hasTakedown && takedownCountryCodes.contains(countryCode)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD
deleted file mode 100644
index 592cfa5b6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD
+++ /dev/null
@@ -1,31 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- "util/util-slf4j-api",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/spam/rtf:safety-result-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- "util/util-slf4j-api",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala
deleted file mode 100644
index 1014e5865..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_visibility_reason
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.spam.rtf.{thriftscala => SPAM}
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient}
-import com.twitter.tweetypie.{thriftscala => TP}
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-import com.twitter.util.logging.Logging
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object VisibilityReason
- extends FeatureWithDefaultOnFailure[TweetCandidate, Option[SPAM.FilteredReason]] {
- override val defaultValue = None
-}
-
-/**
- * A [[BulkCandidateFeatureHydrator]] that hydrates TweetCandidates with VisibilityReason features
- * by [[SPAM.SafetyLevel]] when present. The [[VisibilityReason]] feature represents a VisibilityFiltering
- * [[SPAM.FilteredReason]], which contains safety filtering verdict information including action (e.g.
- * Drop, Avoid) and reason (e.g. Misinformation, Abuse). This feature can inform downstream services'
- * handling and presentation of Tweets (e.g. ad avoidance).
- *
- * @param tweetypieStitchClient used to retrieve Tweet fields for BaseTweetCandidates
- * @param safetyLevel specifies VisibilityFiltering SafetyLabel
- */
-
-@Singleton
-case class TweetVisibilityReasonBulkCandidateFeatureHydrator @Inject() (
- tweetypieStitchClient: TweetypieStitchClient,
- safetyLevel: SPAM.SafetyLevel)
- extends BulkCandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate]
- with Logging {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "TweetVisibilityReason")
-
- override def features: Set[Feature[_, _]] = Set(VisibilityReason)
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[BaseTweetCandidate]]
- ): Stitch[Seq[FeatureMap]] = {
- Stitch
- .traverse(candidates.map(_.candidate.id)) { tweetId =>
- tweetypieStitchClient
- .getTweetFields(
- tweetId = tweetId,
- options = TP.GetTweetFieldsOptions(
- forUserId = query.getOptionalUserId,
- tweetIncludes = Set.empty,
- doNotCache = true,
- visibilityPolicy = TP.TweetVisibilityPolicy.UserVisible,
- safetyLevel = Some(safetyLevel)
- )
- ).liftToTry
- }.map { getTweetFieldsResults: Seq[Try[TP.GetTweetFieldsResult]] =>
- val tweetFields: Seq[Try[TP.TweetFieldsResultFound]] = getTweetFieldsResults.map {
- case Return(TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), _, _)) =>
- Return(found)
- case Return(TP.GetTweetFieldsResult(_, resultState, _, _)) =>
- Throw(
- VisibilityReasonFeatureHydrationFailure(
- s"Unexpected tweet result state: ${resultState}"))
- case Throw(e) =>
- Throw(e)
- }
-
- tweetFields.map { tweetFieldTry =>
- val tweetFilteredReason = tweetFieldTry.map { tweetField =>
- tweetField.suppressReason match {
- case Some(suppressReason) => Some(suppressReason)
- case _ => None
- }
- }
-
- FeatureMapBuilder()
- .add(VisibilityReason, tweetFilteredReason)
- .build()
- }
- }
- }
-}
-
-case class VisibilityReasonFeatureHydrationFailure(message: String)
- extends Exception(s"VisibilityReasonFeatureHydrationFailure($message)")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala
deleted file mode 100644
index 44a187725..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.async
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A [[QueryFeatureHydrator]] with [[AsyncQueryFeatureHydrator]] that hydrated asynchronously for features
- * to be before the step identified in [[hydrateBefore]]
- *
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously
- * @tparam Query The domain model for the query or request
- */
-case class AsyncQueryFeatureHydrator[-Query <: PipelineQuery] private[async] (
- override val hydrateBefore: PipelineStepIdentifier,
- queryFeatureHydrator: QueryFeatureHydrator[Query])
- extends QueryFeatureHydrator[Query]
- with AsyncHydrator {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "Async" + queryFeatureHydrator.identifier.name)
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
- override val features: Set[Feature[_, _]] = queryFeatureHydrator.features
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
-
-/**
- * A [[FeatureStoreV1QueryFeatureHydrator]] with [[AsyncHydrator]] that hydrated asynchronously for features
- * to be before the step identified in [[hydrateBefore]]. We need a standalone class for feature store,
- * different from the above as FStore hydrators are exempt from validations at run time.
- *
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously
- * @tparam Query The domain model for the query or request
- */
-case class AsyncFeatureStoreV1QueryFeatureHydrator[Query <: PipelineQuery] private[async] (
- override val hydrateBefore: PipelineStepIdentifier,
- featureStoreV1QueryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query])
- extends FeatureStoreV1QueryFeatureHydrator[
- Query
- ]
- with AsyncHydrator {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "Async" + featureStoreV1QueryFeatureHydrator.identifier.name)
- override val alerts: Seq[Alert] = featureStoreV1QueryFeatureHydrator.alerts
-
- override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] =
- featureStoreV1QueryFeatureHydrator.features
-
- override val clientBuilder: FeatureStoreV1DynamicClientBuilder =
- featureStoreV1QueryFeatureHydrator.clientBuilder
-}
-
-object AsyncQueryFeatureHydrator {
-
- /**
- * A [[QueryFeatureHydrator]] with [[AsyncQueryFeatureHydrator]] that hydrated asynchronously for features
- * to be before the step identified in [[hydrateBefore]]
- *
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously
- * @tparam Query The domain model for the query or request
- */
- def apply[Query <: PipelineQuery](
- hydrateBefore: PipelineStepIdentifier,
- queryFeatureHydrator: QueryFeatureHydrator[Query]
- ): AsyncQueryFeatureHydrator[Query] =
- new AsyncQueryFeatureHydrator(hydrateBefore, queryFeatureHydrator)
-
- /**
- * A [[FeatureStoreV1QueryFeatureHydrator]] with [[AsyncHydrator]] that hydrated asynchronously for features
- * to be before the step identified in [[hydrateBefore]]. We need a standalone class for feature store,
- * different from the above as FStore hydrators are exempt from validations at run time.
- *
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously
- * @tparam Query The domain model for the query or request
- */
- def apply[Query <: PipelineQuery](
- hydrateBefore: PipelineStepIdentifier,
- featureStoreV1QueryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query]
- ): AsyncFeatureStoreV1QueryFeatureHydrator[Query] =
- new AsyncFeatureStoreV1QueryFeatureHydrator(hydrateBefore, featureStoreV1QueryFeatureHydrator)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD
deleted file mode 100644
index 6bd8f5e31..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel
deleted file mode 100644
index f81495371..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "cr-ml-ranker/thrift/src/main/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "stitch/stitch-core",
- ],
- exports = [
- "cr-ml-ranker/thrift/src/main/thrift:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala
deleted file mode 100644
index 547f14999..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker
-
-import com.twitter.cr_ml_ranker.{thriftscala => t}
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object CrMlRankerCommonFeatures extends Feature[PipelineQuery, t.CommonFeatures]
-object CrMlRankerRankingConfig extends Feature[PipelineQuery, t.RankingConfig]
-
-private[cr_ml_ranker] class CrMlRankerCommonQueryFeatureHydrator(
- crMlRanker: t.CrMLRanker.MethodPerEndpoint,
- rankingConfigSelector: RankingConfigBuilder)
- extends QueryFeatureHydrator[PipelineQuery] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("CrMlRanker")
-
- override val features: Set[Feature[_, _]] =
- Set(CrMlRankerCommonFeatures, CrMlRankerRankingConfig)
-
- override def hydrate(query: PipelineQuery): Stitch[FeatureMap] = {
- val rankingConfig = rankingConfigSelector.apply(query)
- Stitch
- .callFuture(
- crMlRanker.getCommonFeatures(
- t.RankingRequestContext(query.getRequiredUserId, rankingConfig))).map { commonFeatures =>
- FeatureMapBuilder()
- .add(CrMlRankerRankingConfig, rankingConfig)
- .add(CrMlRankerCommonFeatures, commonFeatures)
- .build()
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala
deleted file mode 100644
index 2a5d41d49..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker
-
-import com.twitter.cr_ml_ranker.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Builds a query hydrator that hydrates Common Features for the given Query from CR ML Ranker
- * to be later used to call CR ML Ranker for scoring using the desired [[RankingConfigBuilder]]
- * for building the ranking config.
- */
-@Singleton
-class CrMlRankerCommonQueryFeatureHydratorBuilder @Inject() (
- crMlRanker: t.CrMLRanker.MethodPerEndpoint) {
-
- def build(rankingConfigSelector: RankingConfigBuilder): CrMlRankerCommonQueryFeatureHydrator =
- new CrMlRankerCommonQueryFeatureHydrator(crMlRanker, rankingConfigSelector)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala
deleted file mode 100644
index 2f17683e7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.cr_ml_ranker.{thriftscala => t}
-
-/**
- * Builder for constructing a ranking config from a query
- */
-trait RankingConfigBuilder {
- def apply(query: PipelineQuery): t.RankingConfig
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD
deleted file mode 100644
index fdedd2d2b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/timelines/impression_store:thrift-scala",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "src/thrift/com/twitter/timelines/impression_store:thrift-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala
deleted file mode 100644
index 0d90eed29..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.impressed_tweets
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.storehaus.ReadableStore
-import com.twitter.timelines.impressionstore.thriftscala.ImpressionList
-import com.twitter.util.Future
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Query Feature to store ids of the tweets impressed by the user.
- */
-case object ImpressedTweets extends FeatureWithDefaultOnFailure[PipelineQuery, Seq[Long]] {
- override val defaultValue: Seq[Long] = Seq.empty
-}
-
-/**
- * Enrich the query with a list of tweet ids that the user has already seen.
- */
-@Singleton
-case class ImpressedTweetsQueryFeatureHydrator @Inject() (
- tweetImpressionStore: ReadableStore[Long, ImpressionList])
- extends QueryFeatureHydrator[PipelineQuery] {
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("TweetsToExclude")
-
- override val features: Set[Feature[_, _]] = Set(ImpressedTweets)
-
- override def hydrate(query: PipelineQuery): Stitch[FeatureMap] = {
- query.getOptionalUserId match {
- case Some(userId) =>
- val featureMapResult: Future[FeatureMap] = tweetImpressionStore
- .get(userId).map { impressionListOpt =>
- val tweetIdsOpt = for {
- impressionList <- impressionListOpt
- impressions <- impressionList.impressions
- } yield {
- impressions.map(_.tweetId)
- }
- val tweetIds = tweetIdsOpt.getOrElse(Seq.empty)
- FeatureMapBuilder().add(ImpressedTweets, tweetIds).build()
- }
- Stitch.callFuture(featureMapResult)
- // Non-logged-in users do not have userId, returns empty feature
-
- case None =>
- val featureMapResult = FeatureMapBuilder().add(ImpressedTweets, Seq.empty).build()
- Stitch.value(featureMapResult)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD
deleted file mode 100644
index a9e2c7cc4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala
deleted file mode 100644
index 11d149bd8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.logged_in_only
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] to run only for logged in users
- *
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when query.isLoggedOut is false
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class LoggedInOnlyQueryFeatureHydrator[-Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- queryFeatureHydrator: QueryFeatureHydrator[Query])
- extends QueryFeatureHydrator[Query]
- with Conditionally[Query] {
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "LoggedInOnly" + queryFeatureHydrator.identifier.name)
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
- override val features: Set[Feature[_, _]] = queryFeatureHydrator.features
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, queryFeatureHydrator, !query.isLoggedOut)
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala
deleted file mode 100644
index 60a322e43..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] that hydrates asynchronously for features
- * to be before the step identified in [[hydrateBefore]]
- *
- * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class AsyncParamGatedQueryFeatureHydrator[
- -Query <: PipelineQuery,
- Result <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- override val hydrateBefore: PipelineStepIdentifier,
- queryFeatureHydrator: QueryFeatureHydrator[Query])
- extends QueryFeatureHydrator[Query]
- with Conditionally[Query]
- with AsyncHydrator {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "AsyncParamGated" + queryFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = queryFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam))
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD
deleted file mode 100644
index a9e2c7cc4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala
deleted file mode 100644
index 70b8baeed..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class ParamGatedQueryFeatureHydrator[-Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- enabledParam: Param[Boolean],
- queryFeatureHydrator: QueryFeatureHydrator[Query])
- extends QueryFeatureHydrator[Query]
- with Conditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "ParamGated" + queryFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = queryFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam))
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala
deleted file mode 100644
index 825b0ed4a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] that hydrates asynchronously for features
- * to be before the step identified in [[hydrateBefore]]
- *
- * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off
- * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before.
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class AsyncParamGatedFeatureStoreV1QueryFeatureHydrator[
- Query <: PipelineQuery,
- Result <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- override val hydrateBefore: PipelineStepIdentifier,
- queryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query])
- extends FeatureStoreV1QueryFeatureHydrator[Query]
- with Conditionally[Query]
- with AsyncHydrator {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "AsyncParamGated" + queryFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
-
- override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] =
- queryFeatureHydrator.features
-
- override val clientBuilder: FeatureStoreV1DynamicClientBuilder =
- queryFeatureHydrator.clientBuilder
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam))
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD
deleted file mode 100644
index 7b18d7b06..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala
deleted file mode 100644
index 9fce95a7a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class ParamGatedFeatureStoreV1QueryFeatureHydrator[
- Query <: PipelineQuery,
- Result <: UniversalNoun[Any]
-](
- enabledParam: Param[Boolean],
- queryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query])
- extends FeatureStoreV1QueryFeatureHydrator[Query]
- with Conditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- "ParamGated" + queryFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
-
- override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] =
- queryFeatureHydrator.features
-
- override val clientBuilder: FeatureStoreV1DynamicClientBuilder =
- queryFeatureHydrator.clientBuilder
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam))
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel
deleted file mode 100644
index 579f420ee..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala
deleted file mode 100644
index ac490d174..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.feature_hydrator.query.qualityfactor_gated
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-object QualityFactorGatedQueryFeatureHydrator {
- val IdentifierPrefix = "QfGated"
-}
-
-/**
- * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a qualityFactor threshold.
- * @param pipelineIdentifier identifier of the pipeline that associated with observed quality factor
- * @param qualityFactorInclusiveThreshold the threshold of the quality factor that results in the hydrator being turned off
- * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when quality factor value
- * is above the given inclusive threshold
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class QualityFactorGatedQueryFeatureHydrator[
- -Query <: PipelineQuery with HasQualityFactorStatus,
- Result <: UniversalNoun[Any]
-](
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorInclusiveThreshold: Param[Double],
- queryFeatureHydrator: QueryFeatureHydrator[Query])
- extends QueryFeatureHydrator[Query]
- with Conditionally[Query] {
- import QualityFactorGatedQueryFeatureHydrator._
-
- override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier(
- IdentifierPrefix + queryFeatureHydrator.identifier.name)
-
- override val alerts: Seq[Alert] = queryFeatureHydrator.alerts
-
- override val features: Set[Feature[_, _]] = queryFeatureHydrator.features
-
- override def onlyIf(query: Query): Boolean = Conditionally.and(
- query,
- queryFeatureHydrator,
- query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params(
- qualityFactorInclusiveThreshold))
-
- override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala
deleted file mode 100644
index f0a77ae69..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilter
-
-trait GetAdaptiveLongIntBloomFilter[Query <: PipelineQuery] {
- def apply(query: Query): Option[AdaptiveLongIntBloomFilter]
-}
-
-case class AdaptiveLongIntBloomFilterDedupFilter[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Long]
-](
- getBloomFilter: GetAdaptiveLongIntBloomFilter[Query])
- extends Filter[Query, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier(
- "AdaptiveLongIntBloomFilterDedupFilter")
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val filterResult = getBloomFilter(query)
- .map { bloomFilter =>
- val (kept, removed) =
- candidates.map(_.candidate).partition(candidate => !bloomFilter.contains(candidate.id))
- FilterResult(kept, removed)
- }.getOrElse(FilterResult(candidates.map(_.candidate), Seq.empty))
-
- Stitch.value(filterResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD
deleted file mode 100644
index 371cb91b9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "snowflake/src/main/scala/com/twitter/snowflake/id",
- "src/java/com/twitter/search/common/util/bloomfilter",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "src/thrift/com/twitter/tweetypie:tweet-scala",
- "stitch/stitch-core",
- "stitch/stitch-tweetypie",
- "stitch/stitch-tweetypie/src/main/scala",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "snowflake/src/main/scala/com/twitter/snowflake/id",
- "src/java/com/twitter/search/common/util/bloomfilter",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala
deleted file mode 100644
index d43f2380f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.model.marshalling.request.HasExcludedIds
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-case class ExcludedIdsFilter[
- Query <: PipelineQuery with HasExcludedIds,
- Candidate <: UniversalNoun[Long]
-]() extends Filter[Query, Candidate] {
- override val identifier: FilterIdentifier = FilterIdentifier("ExcludedIds")
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (kept, removed) =
- candidates.map(_.candidate).partition(candidate => !query.excludedIds.contains(candidate.id))
-
- val filterResult = FilterResult(kept = kept, removed = removed)
- Stitch.value(filterResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala
deleted file mode 100644
index 9b1933bab..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object FeatureFilter {
-
- /**
- * Builds a Filter using the Feature name as the FilterIdentifier
- *
- * @see [[FeatureFilter.fromFeature(identifier, feature)]]
- */
- def fromFeature[Candidate <: UniversalNoun[Any]](
- feature: Feature[Candidate, Boolean]
- ): Filter[PipelineQuery, Candidate] =
- FeatureFilter.fromFeature(FilterIdentifier(feature.toString), feature)
-
- /**
- * Builds a Filter that keeps candidates when the provided Boolean Feature is present and True.
- * If the Feature is missing or False, the candidate is removed.
- *
- * {{{
- * Filter.fromFeature(
- * FilterIdentifier("SomeFilter"),
- * feature = SomeFeature
- * )
- * }}}
- *
- * @param identifier A FilterIdentifier for the new filter
- * @param feature A feature of [Candidate, Boolean] type used to determine whether Candidates will be kept
- * when this feature is present and true otherwise they will be removed.
- */
- def fromFeature[Candidate <: UniversalNoun[Any]](
- identifier: FilterIdentifier,
- feature: Feature[Candidate, Boolean]
- ): Filter[PipelineQuery, Candidate] = {
- val i = identifier
-
- new Filter[PipelineQuery, Candidate] {
- override val identifier: FilterIdentifier = i
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (keptCandidates, removedCandidates) = candidates.partition { filterCandidate =>
- filterCandidate.features.getOrElse(feature, false)
- }
-
- Stitch.value(
- FilterResult(
- kept = keptCandidates.map(_.candidate),
- removed = removedCandidates.map(_.candidate)))
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala
deleted file mode 100644
index 552da4b2f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.filter.FeatureConditionalFilter.IdentifierInfix
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Predicate to apply to candidate feature, to determine whether to apply filter.
- * True indicates we will apply the filter. False indicates to keep candidate and not apply filter.
- * @tparam FeatureValue
- */
-trait ShouldApplyFilter[FeatureValue] {
- def apply(feature: FeatureValue): Boolean
-}
-
-/**
- * A filter that applies the [[filter]] for candidates for which [[shouldApplyFilter]] is true, and keeps the others
- * @param feature feature to determine whether to apply underyling filter
- * @param shouldApplyFilter function to determine whether to apply filter
- * @param filter the actual filter to apply if shouldApplyFilter is True
- * @tparam Query The domain model for the query or request
- * @tparam Candidate The type of the candidates
- * @tparam FeatureValueType
- */
-case class FeatureValueConditionalFilter[
- -Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- FeatureValueType
-](
- feature: Feature[Candidate, FeatureValueType],
- shouldApplyFilter: ShouldApplyFilter[FeatureValueType],
- filter: Filter[Query, Candidate])
- extends Filter[Query, Candidate] {
- override val identifier: FilterIdentifier = FilterIdentifier(
- feature.toString + IdentifierInfix + filter.identifier.name
- )
-
- override val alerts: Seq[Alert] = filter.alerts
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (candidatesToFilter, candidatesToKeep) = candidates.partition { candidate =>
- shouldApplyFilter(candidate.features.get(feature))
- }
- filter.apply(query, candidatesToFilter).map { filterResult =>
- FilterResult(
- kept = filterResult.kept ++ candidatesToKeep.map(_.candidate),
- removed = filterResult.removed)
- }
- }
-}
-
-object FeatureConditionalFilter {
- val IdentifierInfix = "FeatureConditional"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala
deleted file mode 100644
index a6248f99e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A filter that checks for presence of a successfully hydrated [[TweetAuthorIdFeature]]
- */
-case class HasAuthorIdFeatureFilter[Candidate <: TweetCandidate]()
- extends Filter[PipelineQuery, Candidate] {
-
- override val identifier = FilterIdentifier("HasAuthorIdFeature")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (kept, removed) = candidates.partition(_.features.getTry(TweetAuthorIdFeature).isReturn)
- Stitch.value(FilterResult(kept.map(_.candidate), removed.map(_.candidate)))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala
deleted file mode 100644
index aa3a4e72f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.filter.ParamGatedFilter.IdentifierPrefix
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[Filter]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this filter on and off
- * @param filter the underlying filter to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Candidate The type of the candidates
- */
-case class ParamGatedFilter[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- enabledParam: Param[Boolean],
- filter: Filter[Query, Candidate])
- extends Filter[Query, Candidate]
- with Filter.Conditionally[Query, Candidate] {
- override val identifier: FilterIdentifier = FilterIdentifier(
- IdentifierPrefix + filter.identifier.name)
- override val alerts: Seq[Alert] = filter.alerts
- override def onlyIf(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): Boolean =
- Conditionally.and(Filter.Input(query, candidates), filter, query.params(enabledParam))
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = filter.apply(query, candidates)
-}
-
-object ParamGatedFilter {
- val IdentifierPrefix = "ParamGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala
deleted file mode 100644
index 158cc636e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Predicate which will be applied to each candidate. True indicates that the candidate will be
- * @tparam Candidate - the type of the candidate
- */
-trait ShouldKeepCandidate[Candidate] {
- def apply(candidate: Candidate): Boolean
-}
-
-object PredicateFilter {
-
- /**
- * Builds a simple Filter out of a predicate function from the candidate to a boolean. For clarity,
- * we recommend including the name of the shouldKeepCandidate parameter.
- *
- * {{{
- * Filter.fromPredicate(
- * FilterIdentifier("SomeFilter"),
- * shouldKeepCandidate = { candidate: UserCandidate => candidate.id % 2 == 0L }
- * )
- * }}}
- *
- * @param identifier A FilterIdentifier for the new filter
- * @param shouldKeepCandidate A predicate function from the candidate. Candidates will be kept
- * when this function returns True.
- */
- def fromPredicate[Candidate <: UniversalNoun[Any]](
- identifier: FilterIdentifier,
- shouldKeepCandidate: ShouldKeepCandidate[Candidate]
- ): Filter[PipelineQuery, Candidate] = {
- val i = identifier
-
- new Filter[PipelineQuery, Candidate] {
- override val identifier: FilterIdentifier = i
-
- /**
- * Filter the list of candidates
- *
- * @return a FilterResult including both the list of kept candidate and the list of removed candidates
- */
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (keptCandidates, removedCandidates) = candidates.map(_.candidate).partition {
- filterCandidate =>
- shouldKeepCandidate(filterCandidate)
- }
-
- Stitch.value(FilterResult(kept = keptCandidates, removed = removedCandidates))
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala
deleted file mode 100644
index 940521c7a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.snowflake.id.SnowflakeId
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-import com.twitter.util.Duration
-
-/**
- * @param maxAgeParam Feature Switch configurable for convenience
- * @tparam Candidate The type of the candidates
- */
-case class SnowflakeIdAgeFilter[Candidate <: UniversalNoun[Long]](
- maxAgeParam: Param[Duration])
- extends Filter[PipelineQuery, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("SnowflakeIdAge")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val maxAge = query.params(maxAgeParam)
-
- val (keptCandidates, removedCandidates) = candidates
- .map(_.candidate)
- .partition { filterCandidate =>
- SnowflakeId.timeFromIdOpt(filterCandidate.id) match {
- case Some(creationTime) =>
- query.queryTime.since(creationTime) <= maxAge
- case _ => false
- }
- }
-
- Stitch.value(FilterResult(kept = keptCandidates, removed = removedCandidates))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala
deleted file mode 100644
index ee83408d9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A [[filter]] that filters candidates based on a country code feature
- *
- * @param countryCodeFeature the feature to filter candidates on
- */
-case class TweetAuthorCountryFilter[Candidate <: BaseTweetCandidate](
- countryCodeFeature: Feature[Candidate, Option[String]])
- extends Filter[PipelineQuery, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("TweetAuthorCountry")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val userCountry = query.getCountryCode
-
- val (keptCandidates, removedCandidates) = candidates.partition { filteredCandidate =>
- val authorCountry = filteredCandidate.features.get(countryCodeFeature)
-
- (authorCountry, userCountry) match {
- case (Some(authorCountryCode), Some(userCountryCode)) =>
- authorCountryCode.equalsIgnoreCase(userCountryCode)
- case _ => true
- }
- }
-
- Stitch.value(
- FilterResult(
- kept = keptCandidates.map(_.candidate),
- removed = removedCandidates.map(_.candidate)
- )
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala
deleted file mode 100644
index 5f87e9080..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A [[filter]] that filters based on whether query user is the author of the tweet. This will NOT filter empty user ids
- * @note It is recommended to apply [[HasAuthorIdFeatureFilter]] before this, as this will FAIL if feature is unavailable
- *
- * @tparam Candidate The type of the candidates
- */
-case class TweetAuthorIsSelfFilter[Candidate <: BaseTweetCandidate]()
- extends Filter[PipelineQuery, Candidate] {
- override val identifier: FilterIdentifier = FilterIdentifier("TweetAuthorIsSelf")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- val (kept, removed) = candidates.partition { candidate =>
- val authorId = candidate.features.get(TweetAuthorIdFeature)
- !query.getOptionalUserId.contains(authorId)
- }
-
- val filterResult = FilterResult(
- kept = kept.map(_.candidate),
- removed = removed.map(_.candidate)
- )
- Stitch.value(filterResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala
deleted file mode 100644
index 88cc82890..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-import com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tweetypie.IsReplyFeature
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Filters out tweets that is a reply to a tweet
- */
-case class TweetIsNotReplyFilter[Candidate <: BaseTweetCandidate]()
- extends Filter[PipelineQuery, Candidate] {
- override val identifier: FilterIdentifier = FilterIdentifier("TweetIsNotReply")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val (kept, removed) = candidates
- .partition { candidate =>
- !candidate.features.get(IsReplyFeature)
- }
-
- val filterResult = FilterResult(
- kept = kept.map(_.candidate),
- removed = removed.map(_.candidate)
- )
-
- Stitch.value(filterResult)
- }
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala
deleted file mode 100644
index 12013df9d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-case class TweetLanguageFilter[Candidate <: BaseTweetCandidate](
- languageCodeFeature: Feature[Candidate, Option[String]])
- extends Filter[PipelineQuery, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("TweetLanguage")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val userAppLanguage = query.getLanguageCode
-
- val (keptCandidates, removedCandidates) = candidates.partition { filterCandidate =>
- val tweetLanguage = filterCandidate.features.get(languageCodeFeature)
-
- (tweetLanguage, userAppLanguage) match {
- case (Some(tweetLanguageCode), Some(userAppLanguageCode)) =>
- tweetLanguageCode.equalsIgnoreCase(userAppLanguageCode)
- case _ => true
- }
- }
-
- Stitch.value(
- FilterResult(
- kept = keptCandidates.map(_.candidate),
- removed = removedCandidates.map(_.candidate)))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala
deleted file mode 100644
index 0f105e679..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.util.logging.Logging
-import com.twitter.product_mixer.component_library.filter.TweetVisibilityFilter._
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.spam.rtf.thriftscala.SafetyLevel
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient}
-import com.twitter.tweetypie.{thriftscala => TP}
-import com.twitter.util.Return
-import com.twitter.util.Try
-
-object TweetVisibilityFilter {
- val DefaultTweetIncludes = Set(TP.TweetInclude.TweetFieldId(TP.Tweet.IdField.id))
- private final val getTweetFieldsFailureMessage = "TweetyPie.getTweetFields failed: "
-}
-
-case class TweetVisibilityFilter[Candidate <: BaseTweetCandidate](
- tweetypieStitchClient: TweetypieStitchClient,
- tweetVisibilityPolicy: TP.TweetVisibilityPolicy,
- safetyLevel: SafetyLevel,
- tweetIncludes: Set[TP.TweetInclude.TweetFieldId] = DefaultTweetIncludes)
- extends Filter[PipelineQuery, Candidate]
- with Logging {
-
- override val identifier: FilterIdentifier = FilterIdentifier("TweetVisibility")
-
- def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
- Stitch
- .traverse(candidates.map(_.candidate.id)) { tweetId =>
- tweetypieStitchClient
- .getTweetFields(tweetId, getTweetFieldsOptions(query.getOptionalUserId))
- .liftToTry
- }
- .map { getTweetFieldsResults: Seq[Try[TP.GetTweetFieldsResult]] =>
- val (checkedSucceeded, checkFailed) = getTweetFieldsResults.partition(_.isReturn)
- checkFailed.foreach(e => warn(() => getTweetFieldsFailureMessage, e.throwable))
- if (checkFailed.nonEmpty) {
- warn(() =>
- s"TweetVisibilityFilter dropped ${checkFailed.size} candidates due to tweetypie failure.")
- }
-
- val allowedTweets = checkedSucceeded.collect {
- case Return(TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), _, _)) =>
- found.tweet.id
- }.toSet
-
- val (kept, removed) =
- candidates.map(_.candidate).partition(candidate => allowedTweets.contains(candidate.id))
-
- FilterResult(kept = kept, removed = removed)
- }
- }
-
- private def getTweetFieldsOptions(userId: Option[Long]) =
- TP.GetTweetFieldsOptions(
- forUserId = userId,
- tweetIncludes = tweetIncludes.toSet,
- doNotCache = true,
- visibilityPolicy = tweetVisibilityPolicy,
- safetyLevel = Some(safetyLevel)
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala
deleted file mode 100644
index fe664e7fe..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.component_library.filter
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-case class UrtUnorderedExcludeIdsCursorFilter[
- Candidate <: UniversalNoun[Long],
- Query <: PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor]
-]() extends Filter[Query, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("UnorderedExcludeIdsCursor")
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val excludeIds = query.pipelineCursor.map(_.excludedIds.toSet).getOrElse(Set.empty)
- val (kept, removed) =
- candidates.map(_.candidate).partition(candidate => !excludeIds.contains(candidate.id))
-
- val filterResult = FilterResult(kept = kept, removed = removed)
- Stitch.value(filterResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel
deleted file mode 100644
index deb6081bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "src/thrift/com/twitter/socialgraph:thrift-scala",
- "strato/config/columns/lists/reads:core-strato-client",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "strato/config/columns/lists/reads:core-strato-client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala
deleted file mode 100644
index a3a08af32..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.filter.list_visibility
-
-import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.socialgraph.thriftscala.SocialgraphList
-import com.twitter.stitch.Stitch
-import com.twitter.strato.catalog.Fetch
-import com.twitter.strato.generated.client.lists.reads.CoreOnListClientColumn
-
-/* This Filter queries the core.List.strato column
- * on Strato, and filters out any lists that are not
- * returned. core.List.strato performs an authorization
- * check, and does not return lists the viewer is not authorized
- * to have access to. */
-class ListVisibilityFilter[Candidate <: UniversalNoun[Long]](
- listsColumn: CoreOnListClientColumn)
- extends Filter[PipelineQuery, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("ListVisibility")
-
- def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- val listCandidates = candidates.collect {
- case CandidateWithFeatures(candidate: TwitterListCandidate, _) => candidate
- }
-
- Stitch
- .traverse(
- listCandidates.map(_.id)
- ) { listId =>
- listsColumn.fetcher.fetch(listId)
- }.map { fetchResults =>
- fetchResults.collect {
- case Fetch.Result(Some(list: SocialgraphList), _) => list.id
- }
- }.map { allowedListIds =>
- val (kept, excluded) = candidates.map(_.candidate).partition {
- case candidate: TwitterListCandidate => allowedListIds.contains(candidate.id)
- case _ => true
- }
- FilterResult(kept, excluded)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel
deleted file mode 100644
index afd5204bd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala
deleted file mode 100644
index dd8cee2bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.filter.tweet_impression
-
-import com.twitter.product_mixer.component_library.feature_hydrator.query.impressed_tweets.ImpressedTweets
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Filters out tweets that the user has seen
- */
-case class TweetImpressionFilter[Candidate <: BaseTweetCandidate](
-) extends Filter[PipelineQuery, Candidate] {
-
- override val identifier: FilterIdentifier = FilterIdentifier("TweetImpression")
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]] = {
-
- // Set of Tweets that have impressed the user
- val impressedTweetsSet: Set[Long] = query.features match {
- case Some(featureMap) => featureMap.getOrElse(ImpressedTweets, Seq.empty).toSet
- case None => Set.empty
- }
-
- val (keptCandidates, removedCandidates) = candidates.partition { filteredCandidate =>
- !impressedTweetsSet.contains(filteredCandidate.candidate.id)
- }
-
- Stitch.value(FilterResult(keptCandidates.map(_.candidate), removedCandidates.map(_.candidate)))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD
deleted file mode 100644
index 35e791b9b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "src/scala/com/twitter/ml/featurestore/lib",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala
deleted file mode 100644
index 7fc6fd501..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object DefinedCountryCodeGate extends Gate[PipelineQuery] {
- override val identifier: GateIdentifier = GateIdentifier("DefinedCountryCode")
-
- override def shouldContinue(query: PipelineQuery): Stitch[Boolean] =
- Stitch.value(query.getCountryCode.isDefined)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala
deleted file mode 100644
index 8530e4b7b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.gate.GateResult
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import com.twitter.util.Return
-import com.twitter.util.Throw
-
-trait ShouldContinue[Value] {
-
- /** Given the [[Feature]] value, returns whether the execution should continue */
- def apply(featureValue: Value): Boolean
-
- /** If the [[Feature]] is a failure, use this value */
- def onFailedFeature(t: Throwable): GateResult = GateResult.Stop
-
- /**
- * If the [[Feature]], or [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]],
- * is missing use this value
- */
- def onMissingFeature: GateResult = GateResult.Stop
-}
-
-object FeatureGate {
-
- def fromFeature(
- feature: Feature[_, Boolean]
- ): FeatureGate[Boolean] =
- FeatureGate.fromFeature(GateIdentifier(feature.toString), feature)
-
- def fromNegatedFeature(
- feature: Feature[_, Boolean]
- ): FeatureGate[Boolean] =
- FeatureGate.fromNegatedFeature(GateIdentifier(feature.toString), feature)
-
- def fromFeature(
- gateIdentifier: GateIdentifier,
- feature: Feature[_, Boolean]
- ): FeatureGate[Boolean] =
- FeatureGate[Boolean](gateIdentifier, feature, identity)
-
- def fromNegatedFeature(
- gateIdentifier: GateIdentifier,
- feature: Feature[_, Boolean]
- ): FeatureGate[Boolean] =
- FeatureGate[Boolean](gateIdentifier, feature, !identity(_))
-
-}
-
-/**
- * A [[Gate]] that is actuated based upon the value of the provided feature
- */
-case class FeatureGate[Value](
- gateIdentifier: GateIdentifier,
- feature: Feature[_, Value],
- continue: ShouldContinue[Value])
- extends Gate[PipelineQuery] {
-
- override val identifier: GateIdentifier = gateIdentifier
-
- override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = {
- Stitch
- .value(
- query.features.map(_.getTry(feature)) match {
- case Some(Return(value)) => continue(value)
- case Some(Throw(_: MissingFeatureException)) => continue.onMissingFeature.continue
- case Some(Throw(t)) => continue.onFailedFeature(t).continue
- case None =>
- throw PipelineFailure(
- MisconfiguredFeatureMapFailure,
- "Expected a FeatureMap to be present but none was found, ensure that your" +
- "PipelineQuery has a FeatureMap configured before gating on Feature values"
- )
- }
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala
deleted file mode 100644
index ef2d485ac..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Gate used in first page. Use request cursor to determine if the gate should be open or closed.
- */
-object FirstPageGate extends Gate[PipelineQuery with HasPipelineCursor[_]] {
-
- override val identifier: GateIdentifier = GateIdentifier("FirstPage")
-
- // If cursor is first page, then gate should return continue, otherwise return stop
- override def shouldContinue(query: PipelineQuery with HasPipelineCursor[_]): Stitch[Boolean] =
- Stitch.value(query.isFirstPage)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala
deleted file mode 100644
index db3406edf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A Gate that only continues if the previously returned candidates are empty. This is useful
- * for gating dependent candidate pipelines that are intedned to be used as a backfill when there
- * are no candidates available.
- */
-case class NoCandidatesGate(scope: CandidateScope) extends QueryAndCandidateGate[PipelineQuery] {
- override val identifier: GateIdentifier = GateIdentifier("NoCandidates")
- override def shouldContinue(
- query: PipelineQuery,
- candidates: Seq[CandidateWithDetails]
- ): Stitch[Boolean] = Stitch.value(scope.partition(candidates).candidatesInScope.isEmpty)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala
deleted file mode 100644
index 303fe3d13..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object NonEmptyAdsQueryStringGate extends Gate[PipelineQuery with AdsQuery] {
- override val identifier: GateIdentifier = GateIdentifier("NonEmptyAdsQueryString")
-
- override def shouldContinue(query: PipelineQuery with AdsQuery): Stitch[Boolean] = {
- val queryString = query.searchRequestContext.flatMap(_.queryString)
- Stitch.value(queryString.exists(_.trim.nonEmpty))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala
deleted file mode 100644
index cdc6fe13d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A Gate that only continues if the previously returned candidates are not empty. This is useful
- * for gating dependent candidate pipelines that are intended to only be used if a previous pipeline
- * completed successfully.
- */
-case class NonEmptyCandidatesGate(scope: CandidateScope)
- extends QueryAndCandidateGate[PipelineQuery] {
- override val identifier: GateIdentifier = GateIdentifier("NonEmptyCandidates")
- override def shouldContinue(
- query: PipelineQuery,
- candidates: Seq[CandidateWithDetails]
- ): Stitch[Boolean] = Stitch.value(scope.partition(candidates).candidatesInScope.nonEmpty)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala
deleted file mode 100644
index e0fc5e4b6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.stitch.Stitch
-
-/**
- * A Gate that only continues if the quality factor value of the pipeline is above the given
- * threshold. This is useful for disabling an expensive function when the pipeline is under pressure
- * (quality factor is low).
- */
-case class QualityFactorGate(pipelineIdentifier: ComponentIdentifier, threshold: Double)
- extends Gate[PipelineQuery with HasQualityFactorStatus] {
-
- override val identifier: GateIdentifier = GateIdentifier(
- s"${pipelineIdentifier.name}QualityFactor")
-
- override def shouldContinue(
- query: PipelineQuery with HasQualityFactorStatus
- ): Stitch[Boolean] =
- Stitch.value(query.getQualityFactorCurrentValue(pipelineIdentifier) >= threshold)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala
deleted file mode 100644
index 3e859549d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.component_library.gate.any_candidates_without_feature
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * A gate that enables a component only if any candidates are missing a specific feature.
- * You can restrict which candidates to check with the scope parameter.
- * This is most commonly used to do backfill scoring, where you can have one Scoring Pipeline that
- * might return a score feature "FeatureA" and another sequential pipeline that you only want to run
- * if the previous scoring pipeline fails to hydrate for all candidates.
- * @param identifier Unique identifier for this gate. Typically, AnyCandidatesWithout{YourFeature}.
- * @param scope A [[CandidateScope]] to specify which candidates to check.
- * @param missingFeature The feature that should be missing for any of the candidates for this gate to continue
- */
-case class AnyCandidatesWithoutFeatureGate(
- override val identifier: GateIdentifier,
- scope: CandidateScope,
- missingFeature: Feature[_, _])
- extends QueryAndCandidateGate[PipelineQuery] {
-
- override def shouldContinue(
- query: PipelineQuery,
- candidates: Seq[CandidateWithDetails]
- ): Stitch[Boolean] =
- Stitch.value(scope.partition(candidates).candidatesInScope.exists { candidateWithDetails =>
- !candidateWithDetails.features.getSuccessfulFeatures.contains(missingFeature)
- })
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel
deleted file mode 100644
index 7d26d6370..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala
deleted file mode 100644
index 650307acd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait BaseArticleCandidate extends UniversalNoun[Int]
-
-/**
- * Canonical ArticleCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class ArticleCandidate private (
- override val id: Int)
- extends BaseArticleCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ArticleCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: ArticleCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object ArticleCandidate {
- def apply(id: Int): ArticleCandidate = new ArticleCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala
deleted file mode 100644
index 9c17dc647..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical AudioSpaceCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class AudioSpaceCandidate private (
- override val id: String)
- extends UniversalNoun[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[AudioSpaceCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: AudioSpaceCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object AudioSpaceCandidate {
- def apply(id: String): AudioSpaceCandidate = new AudioSpaceCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD
deleted file mode 100644
index e92b67378..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala
deleted file mode 100644
index 3c7980de1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical CardCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CardCandidate private (
- override val id: String)
- extends UniversalNoun[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CardCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CardCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object CardCandidate {
- def apply(id: String): CardCandidate = new CardCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala
deleted file mode 100644
index 8970e7840..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical CommerceProductCandidate model which encapsulates information about a specific Product.
- * Always prefer this version over all other variants. For example, iPhone 14, 128 GB, White. When a
- * user clicks on a CommerceProduct, they will be taken to the specific product page.
- *
- * @note Both CommerceProduct and CommerceProductGroups (below) can be shown in the same
- * TimelineModule (i.e Carousel)
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CommerceProductCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CommerceProductCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CommerceProductCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object CommerceProductCandidate {
- def apply(id: Long): CommerceProductCandidate = new CommerceProductCandidate(id)
-}
-
-/**
- * Canonical CommerceProductGroupCandidate model which encapsulates information about a Single
- * Product Type and its corresponding versions. Always prefer this version over all other variants.
- * For example:
- * iPhone 14
- * - 128 GB, White
- * - 128 GB, Blue
- * - 1TB, Grey
- * When a user clicks on a Product Group, they will be shown information about all of the possible
- * versions of the top level product.
- *
- * @note Both CommerceProduct (above) and CommerceProductGroups can be shown in the same
- * TimelineModule (i.e Carousel)
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CommerceProductGroupCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CommerceProductGroupCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CommerceProductGroupCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object CommerceProductGroupCandidate {
- def apply(id: Long): CommerceProductGroupCandidate = new CommerceProductGroupCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala
deleted file mode 100644
index fd9c82cd9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-sealed trait CursorType
-case object PreviousCursor extends CursorType
-case object NextCursor extends CursorType
-
-/**
- * Canonical CursorCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CursorCandidate private (
- override val id: Long,
- val value: String,
- val cursorType: CursorType)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CursorCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CursorCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && value == candidate.value && cursorType == candidate.cursorType))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- 31 * (
- id.##
- ) + value.##
- ) + cursorType.##
-}
-
-object CursorCandidate {
- def apply(id: Long, value: String, cursorType: CursorType): CursorCandidate =
- new CursorCandidate(id, value, cursorType)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala
deleted file mode 100644
index 594fe96b5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait BaseDMConvoCandidate extends UniversalNoun[String] {
- def lastReadableEventId: Option[Long]
-}
-
-/**
- * Canonical DMConvoCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class DMConvoCandidate private (
- override val id: String,
- override val lastReadableEventId: Option[Long])
- extends BaseDMConvoCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DMConvoCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: DMConvoCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && lastReadableEventId == candidate.lastReadableEventId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + lastReadableEventId.##
-}
-
-object DMConvoCandidate {
- def apply(id: String, lastReadableEventId: Option[Long]): DMConvoCandidate =
- new DMConvoCandidate(id, lastReadableEventId)
-}
-
-/**
- * Canonical DMConvoSearchCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class DMConvoSearchCandidate private (
- override val id: String,
- override val lastReadableEventId: Option[Long])
- extends BaseDMConvoCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DMConvoSearchCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: DMConvoSearchCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && lastReadableEventId == candidate.lastReadableEventId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + lastReadableEventId.##
-}
-
-object DMConvoSearchCandidate {
- def apply(id: String, lastReadableEventId: Option[Long]): DMConvoSearchCandidate =
- new DMConvoSearchCandidate(id, lastReadableEventId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala
deleted file mode 100644
index 370b31933..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical DM Events such as Message Create, Conversation Create, Join conversation, etc model.
- * Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class DMEventCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DMEventCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: DMEventCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object DMEventCandidate {
- def apply(id: Long): DMEventCandidate = new DMEventCandidate(id)
-}
-
-/**
- * Represent DM Events such as Message Create, Conversation Create, Join conversation, etc.
- *
- * @note historically this was used to represent events from Elastic
- * Search rather than Strato. Now deprecated in favor of DMEvent.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- *
- */
-@deprecated("Prefer DMEvent")
-final class DMMessageSearchCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DMMessageSearchCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: DMMessageSearchCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object DMMessageSearchCandidate {
- def apply(id: Long): DMMessageSearchCandidate = new DMMessageSearchCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala
deleted file mode 100644
index 3a884f8cd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical GenericSummaryCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class GenericSummaryCandidate private (
- override val id: String)
- extends UniversalNoun[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[GenericSummaryCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: GenericSummaryCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object GenericSummaryCandidate {
- def apply(id: String): GenericSummaryCandidate = new GenericSummaryCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala
deleted file mode 100644
index 444fb82f0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical LabelCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class LabelCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[LabelCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: LabelCandidate =>
- ((this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id)))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object LabelCandidate {
- def apply(id: Long): LabelCandidate = new LabelCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala
deleted file mode 100644
index 77464823f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical MomentAnnotationCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class MomentAnnotationCandidate private (
- override val id: Long,
- val text: Option[String],
- val header: Option[String])
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[MomentAnnotationCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: MomentAnnotationCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && text == candidate.text && header == candidate.header))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- 31 * (
- id.##
- ) + text.##
- ) + header.##
-}
-
-object MomentAnnotationCandidate {
- def apply(
- id: Long,
- text: Option[String],
- header: Option[String]
- ): MomentAnnotationCandidate = new MomentAnnotationCandidate(id, text, header)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala
deleted file mode 100644
index 5ebaf0d93..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala
+++ /dev/null
@@ -1,433 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-sealed trait BasePromptCandidate[+T] extends UniversalNoun[T]
-
-/**
- * Canonical InlinePromptCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class InlinePromptCandidate private (
- override val id: String)
- extends BasePromptCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[InlinePromptCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: InlinePromptCandidate =>
- ((this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id)))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object InlinePromptCandidate {
- def apply(id: String): InlinePromptCandidate = new InlinePromptCandidate(id)
-}
-
-/**
- * Canonical CompactPromptCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CompactPromptCandidate private (
- override val id: Long)
- extends BasePromptCandidate[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CompactPromptCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CompactPromptCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object CompactPromptCandidate {
- def apply(id: Long): CompactPromptCandidate = new CompactPromptCandidate(id)
-}
-
-/**
- * Canonical FullCoverPromptCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class FullCoverPromptCandidate private (
- override val id: String)
- extends BasePromptCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[FullCoverPromptCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: FullCoverPromptCandidate =>
- ((this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id)))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object FullCoverPromptCandidate {
- def apply(id: String): FullCoverPromptCandidate = new FullCoverPromptCandidate(id)
-}
-
-/**
- * Canonical HalfCoverPromptCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class HalfCoverPromptCandidate private (
- override val id: String)
- extends BasePromptCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[HalfCoverPromptCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: HalfCoverPromptCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object HalfCoverPromptCandidate {
- def apply(id: String): HalfCoverPromptCandidate = new HalfCoverPromptCandidate(id)
-}
-
-/**
- * Canonical PromptCarouselTileCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class PromptCarouselTileCandidate private (
- override val id: Long)
- extends BasePromptCandidate[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[PromptCarouselTileCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: PromptCarouselTileCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object PromptCarouselTileCandidate {
- def apply(id: Long): PromptCarouselTileCandidate = new PromptCarouselTileCandidate(id)
-}
-
-/**
- * Canonical RelevancePromptCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class RelevancePromptCandidate private (
- override val id: String,
- val position: Option[Int])
- extends BasePromptCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[RelevancePromptCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: RelevancePromptCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && position == candidate.position))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + position.##
-}
-
-object RelevancePromptCandidate {
- def apply(
- id: String,
- position: Option[Int] = None
- ): RelevancePromptCandidate =
- new RelevancePromptCandidate(id, position)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala
deleted file mode 100644
index 7c5e1b8ad..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical ShowAlertCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class ShowAlertCandidate private (
- override val id: String,
- val userIds: Seq[Long])
- extends UniversalNoun[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ShowAlertCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: ShowAlertCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && userIds == candidate.userIds))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + userIds.##
-}
-
-object ShowAlertCandidate {
- def apply(id: String, userIds: Seq[Long]): ShowAlertCandidate =
- new ShowAlertCandidate(id, userIds)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala
deleted file mode 100644
index 53844c419..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait BaseTopicCandidate extends UniversalNoun[Long]
-
-/**
- * Canonical TopicCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class TopicCandidate private (
- override val id: Long)
- extends BaseTopicCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TopicCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TopicCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object TopicCandidate {
- def apply(id: Long): TopicCandidate = new TopicCandidate(id)
-}
-
-/**
- * Canonical CategorizedTopicCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-@deprecated("Prefer TopicCandidate")
-final class CategorizedTopicCandidate private (
- override val id: Long,
- val categoryId: Option[Long],
- val categoryName: Option[String])
- extends BaseTopicCandidate {
-
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CategorizedTopicCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CategorizedTopicCandidate =>
- (
- (this eq candidate)
- || (
- (hashCode == candidate.hashCode)
- && (id == candidate.id && categoryId == candidate.categoryId && categoryName == candidate.categoryName)
- )
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- 31 * (
- id.##
- ) + categoryId.##
- ) + categoryName.##
-}
-
-object CategorizedTopicCandidate {
- def apply(
- id: Long,
- categoryId: Option[Long] = None,
- categoryName: Option[String] = None
- ): CategorizedTopicCandidate =
- new CategorizedTopicCandidate(id, categoryId, categoryName)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala
deleted file mode 100644
index bea57aa51..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.fasterxml.jackson.annotation.JsonTypeName
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-// JSON type annotations are needed for identifying renderable entities to Turntable, most candidates
-// do not need them.
-@JsonTypeName("tweet")
-trait BaseTweetCandidate extends UniversalNoun[Long]
-
-/**
- * Canonical TweetCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class TweetCandidate private (
- override val id: Long)
- extends BaseTweetCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TweetCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TweetCandidate =>
- ((this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id)))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object TweetCandidate {
- def apply(id: Long): TweetCandidate = new TweetCandidate(id)
-}
-
-/**
- * Tweet Author User ID of a given Tweet Candidate. This is typically needed when hydrating tweet
- * author extended features in Feature Store (e.g, [[TweetCandidateAuthorIdEntity]]). This feature
- * is typically extracted by hydrating it from Tweetypie, or extracting it in your candidate source
- * if it returns the Author ID alongside Tweet ID using a [[CandidatePipelineResultsTransformer]]
- */
-object TweetAuthorIdFeature extends Feature[TweetCandidate, Long]
-
-/**
- * Whether the tweet should be pinned when marshalled to URT or not.
- * See [[com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder]]
- */
-object IsPinnedFeature extends Feature[TweetCandidate, Boolean]
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala
deleted file mode 100644
index b9befe9f6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical TwitterListCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class TwitterListCandidate private (
- override val id: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TwitterListCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TwitterListCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object TwitterListCandidate {
- def apply(id: Long): TwitterListCandidate = new TwitterListCandidate(id)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala
deleted file mode 100644
index 9e34e5054..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate
-
-import com.fasterxml.jackson.annotation.JsonTypeName
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-// JSON type annotations are needed for identifying renderable entities to Turntable, most candidates
-// do not need them.
-@JsonTypeName("user")
-trait BaseUserCandidate extends UniversalNoun[Long]
-
-/**
- * Canonical UserCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class UserCandidate private (
- override val id: Long)
- extends BaseUserCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[UserCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: UserCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object UserCandidate {
- def apply(id: Long): UserCandidate = new UserCandidate(id)
-}
-
-/**
- * Feature to indicate whether a rendered user candidate should be marked unread in URT. Used in
- * [[UserCandidateUrtItemBuilder]] when decorating the candidate.r
- */
-object IsMarkUnreadFeature extends Feature[BaseUserCandidate, Boolean]
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala
deleted file mode 100644
index b00f4505f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.ads
-
-import com.twitter.adserver.{thriftscala => adsthrift}
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * An [[AdsCandidate]] represents a piece of promoted content.
- *
- * This candidate class stores a reference to the adImpression, which is the common thrift structure
- * used by the Ads team to represent an ad.
- *
- * Goldfinch, the ads-injection library, consumes the [[AdImpression]].
- */
-sealed trait AdsCandidate extends UniversalNoun[Any] {
- val adImpression: adsthrift.AdImpression
-}
-
-/**
- * Canonical AdsTweetCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class AdsTweetCandidate private (
- override val id: Long,
- override val adImpression: adsthrift.AdImpression)
- extends AdsCandidate
- with BaseTweetCandidate {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[AdsTweetCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: AdsTweetCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && adImpression == candidate.adImpression))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + adImpression.##
-}
-
-object AdsTweetCandidate {
- def apply(id: Long, adImpression: adsthrift.AdImpression): AdsTweetCandidate =
- new AdsTweetCandidate(id, adImpression)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD
deleted file mode 100644
index 3627c158e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model/promoted",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- ],
- exports = [
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model/promoted",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "src/thrift/com/twitter/ads/adserver:adserver_common-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala
deleted file mode 100644
index 42622b6c4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.hubble
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.slice.AdType
-
-/**
- * Canonical AdCreativeCandidate model which describes an Ad Creative from an ad management
- * perspective. It can be a tweet, or account, and has a 1:n relationship with ad units. Always
- * prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class AdCreativeCandidate private (
- // This is the creativeId, but needs to be named ID to confirm to UniversalNoun
- override val id: Long,
- val adType: AdType,
- val adAccountId: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[AdCreativeCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: AdCreativeCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && adType == candidate.adType && adAccountId == candidate.adAccountId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- 31 * (
- id.##
- ) + adType.##
- ) + adAccountId.##
-}
-
-object AdCreativeCandidate {
- def apply(
- id: Long,
- adType: AdType,
- adAccountId: Long
- ): AdCreativeCandidate =
- new AdCreativeCandidate(id, adType, adAccountId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala
deleted file mode 100644
index 60f726dac..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.hubble
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical AdGroupCandidate model which describes an "Ad Group" from the the Ad Management
- * perspective. It is based on the LineItem table in Ads DB, and provides an ad group for
- * advertisers to manage and report different line items belonging to a single ad. Always prefer
- * this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class AdGroupCandidate private (
- override val id: Long, // This is the ad_group_id, renamed to ID to conform to UniversalNoun
- val adAccountId: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[AdGroupCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: AdGroupCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && adAccountId == candidate.adAccountId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + adAccountId.##
-}
-
-object AdGroupCandidate {
- def apply(
- id: Long,
- adAccountId: Long
- ): AdGroupCandidate =
- new AdGroupCandidate(id, adAccountId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala
deleted file mode 100644
index 1a96ff212..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.hubble
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical AdUnitCandidate model which describes an "Ad" from the Ad Management perspective. It is
- * based on the AdUnit table in Ads DB, and provides a candidate for advertisers to manage and
- * report on their advertising configurations.Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class AdUnitCandidate private (
- // This is the adUnitId, but needs to be named ID to confirm to UniversalNoun
- override val id: Long,
- val adAccountId: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[AdUnitCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: AdUnitCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && adAccountId == candidate.adAccountId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + adAccountId.##
-}
-
-object AdUnitCandidate {
- def apply(
- id: Long,
- adAccountId: Long
- ): AdUnitCandidate =
- new AdUnitCandidate(id, adAccountId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD
deleted file mode 100644
index d9e52eeb9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala
deleted file mode 100644
index 7a7ea3481..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.hubble
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical CampaignCandidate model which describes a "Campaign" from the Ads Management
- * perspective. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class CampaignCandidate private (
- // This is the campaignId, but needs to be named id to conform to UniversalNoun
- override val id: Long,
- val adAccountId: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CampaignCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: CampaignCandidate =>
- ((this eq candidate)
- || ((hashCode == candidate.hashCode) && (id == candidate.id)))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = id.##
-}
-
-object CampaignCandidate {
- def apply(id: Long, adAccountId: Long): CampaignCandidate =
- new CampaignCandidate(id, adAccountId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala
deleted file mode 100644
index c119280a0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.hubble
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/**
- * Canonical FundingSourceCandidate model which describes a "Funding Instrument" from the the Ad
- * Management perspective. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class FundingSourceCandidate private (
- override val id: Long,
- val adAccountId: Long)
- extends UniversalNoun[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[FundingSourceCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: FundingSourceCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && adAccountId == candidate.adAccountId))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + adAccountId.##
-}
-
-object FundingSourceCandidate {
- def apply(
- id: Long,
- adAccountId: Long
- ): FundingSourceCandidate = new FundingSourceCandidate(id, adAccountId)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD
deleted file mode 100644
index 2f373e3e1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala
deleted file mode 100644
index 4c6cd70ad..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala
+++ /dev/null
@@ -1,296 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.suggestion
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.slice.TypeaheadMetadata
-
-/**
- * Represents a query suggestion in typeahead
- */
-sealed trait BaseQuerySuggestionCandidate[+T] extends UniversalNoun[T]
-
-/**
- * Canonical QuerySuggestionCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class QuerySuggestionCandidate private (
- override val id: String,
- val metadata: Option[TypeaheadMetadata])
- extends BaseQuerySuggestionCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[QuerySuggestionCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: QuerySuggestionCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && metadata == candidate.metadata))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + metadata.##
-}
-
-object QuerySuggestionCandidate {
- def apply(
- id: String,
- metadata: Option[TypeaheadMetadata] = None
- ): QuerySuggestionCandidate = new QuerySuggestionCandidate(id, metadata)
-}
-
-/**
- * Canonical TypeaheadQueryCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- *
- */
-final class TypeaheadQueryCandidate(
- override val id: String,
- val score: Option[Double])
- extends BaseQuerySuggestionCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TypeaheadQueryCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TypeaheadQueryCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && score == candidate.score))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + score.##
-}
-
-object TypeaheadQueryCandidate {
- def apply(id: String, score: Option[Double]): TypeaheadQueryCandidate =
- new TypeaheadQueryCandidate(id, score)
-}
-
-final class TypeaheadEventCandidate private (
- override val id: Long,
- val metadata: Option[TypeaheadMetadata])
- extends BaseQuerySuggestionCandidate[Long] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TypeaheadQueryCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TypeaheadEventCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && metadata == candidate.metadata))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + metadata.##
-}
-
-object TypeaheadEventCandidate {
- def apply(
- id: Long,
- metadata: Option[TypeaheadMetadata] = None
- ): TypeaheadEventCandidate = new TypeaheadEventCandidate(id, metadata)
-}
-
-/**
- * Canonical TweetAnnotationQueryCandidate model. Always prefer this version over all other variants.
- *
- * TODO Remove score from the candidate and use a Feature instead
- */
-final class TweetAnnotationQueryCandidate private (
- override val id: String,
- val score: Option[Double])
- extends BaseQuerySuggestionCandidate[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TweetAnnotationQueryCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: TweetAnnotationQueryCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && score == candidate.score))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- id.##
- ) + score.##
-}
-
-object TweetAnnotationQueryCandidate {
- def apply(id: String, score: Option[Double]): TweetAnnotationQueryCandidate =
- new TweetAnnotationQueryCandidate(id, score)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala
deleted file mode 100644
index c946d29c3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.suggestion
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingActionType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.TextResult
-
-/**
- * Canonical SpellingSuggestionCandidate model. Always prefer this version over all other variants.
- *
- * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]]
- * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the
- * features come from the candidate source itself (as opposed to hydrated via a
- * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]),
- * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]]
- * can be used to extract features from the candidate source response.
- *
- * @note This class should always remain `final`. If for any reason the `final` modifier is removed,
- * the equals() implementation must be updated in order to handle class inheritor equality
- * (see note on the equals method below)
- */
-final class SpellingSuggestionCandidate private (
- override val id: String,
- val textResult: TextResult,
- val spellingActionType: Option[SpellingActionType],
- val originalQuery: Option[String])
- extends UniversalNoun[String] {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[SpellingSuggestionCandidate]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case candidate: SpellingSuggestionCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id && textResult == candidate.textResult && spellingActionType == candidate.spellingActionType && originalQuery == candidate.originalQuery))
- )
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated candidate
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int =
- 31 * (
- 31 * (
- 31 * (
- id.##
- ) + textResult.##
- ) + spellingActionType.##
- ) + originalQuery.##
-}
-
-object SpellingSuggestionCandidate {
- def apply(
- id: String,
- textResult: TextResult,
- spellingActionType: Option[SpellingActionType],
- originalQuery: Option[String]
- ): SpellingSuggestionCandidate =
- new SpellingSuggestionCandidate(id, textResult, spellingActionType, originalQuery)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD
deleted file mode 100644
index 9574c702e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala
deleted file mode 100644
index acb0c351c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.twitter.product_mixer.component_library.model.candidate.trends_events
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.GroupedTrend
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType
-
-/**
- * An [[UnifiedTrendEventCandidate]] represents a piece of Event or Trend content.
- * The Event and Trend candidate are represented by different types of keys that Event has a Long
- * eventId while Trend has a String trendName.
- */
-sealed trait UnifiedTrendEventCandidate[+T] extends UniversalNoun[T]
-
-final class UnifiedEventCandidate private (
- override val id: Long)
- extends UnifiedTrendEventCandidate[Long] {
-
- override def canEqual(that: Any): Boolean = this.isInstanceOf[UnifiedEventCandidate]
-
- override def equals(that: Any): Boolean = {
- that match {
- case candidate: UnifiedEventCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ => false
- }
- }
-
- override val hashCode: Int = id.##
-}
-
-object UnifiedEventCandidate {
- def apply(id: Long): UnifiedEventCandidate = new UnifiedEventCandidate(id)
-}
-
-/**
- * Text description of an Event. Usually this is extracted from curated Event metadata
- */
-object EventTitleFeature extends Feature[UnifiedEventCandidate, String]
-
-/**
- * Display type of an Event. This will be used for client to differentiate if this Event will be
- * displayed as a normal cell, a hero, etc.
- */
-object EventDisplayType extends Feature[UnifiedEventCandidate, EventSummaryDisplayType]
-
-/**
- * URL that servces as the landing page of an Event
- */
-object EventUrl extends Feature[UnifiedEventCandidate, Url]
-
-/**
- * Use to render an Event cell's editorial image
- */
-object EventImage extends Feature[UnifiedEventCandidate, Option[ImageVariant]]
-
-/**
- * Localized time string like "LIVE" or "Last Night" that is used to render the Event cell
- */
-object EventTimeString extends Feature[UnifiedEventCandidate, Option[String]]
-
-final class UnifiedTrendCandidate private (
- override val id: String)
- extends UnifiedTrendEventCandidate[String] {
-
- override def canEqual(that: Any): Boolean = this.isInstanceOf[UnifiedTrendCandidate]
-
- override def equals(that: Any): Boolean = {
- that match {
- case candidate: UnifiedTrendCandidate =>
- (
- (this eq candidate)
- || ((hashCode == candidate.hashCode)
- && (id == candidate.id))
- )
- case _ => false
- }
- }
-
- override val hashCode: Int = id.##
-}
-
-object UnifiedTrendCandidate {
- def apply(id: String): UnifiedTrendCandidate = new UnifiedTrendCandidate(id)
-}
-
-object TrendNormalizedTrendName extends Feature[UnifiedTrendCandidate, String]
-
-object TrendTrendName extends Feature[UnifiedTrendCandidate, String]
-
-object TrendUrl extends Feature[UnifiedTrendCandidate, Url]
-
-object TrendDescription extends Feature[UnifiedTrendCandidate, Option[String]]
-
-object TrendTweetCount extends Feature[UnifiedTrendCandidate, Option[Int]]
-
-object TrendDomainContext extends Feature[UnifiedTrendCandidate, Option[String]]
-
-object TrendGroupedTrends extends Feature[UnifiedTrendCandidate, Option[Seq[GroupedTrend]]]
-
-object PromotedTrendNameFeature extends Feature[UnifiedTrendCandidate, Option[String]]
-
-object PromotedTrendDescriptionFeature extends Feature[UnifiedTrendCandidate, Option[String]]
-
-object PromotedTrendAdvertiserNameFeature extends Feature[UnifiedTrendCandidate, Option[String]]
-
-object PromotedTrendIdFeature extends Feature[UnifiedTrendCandidate, Option[Long]]
-
-object PromotedTrendDisclosureTypeFeature
- extends Feature[UnifiedTrendCandidate, Option[DisclosureType]]
-
-object PromotedTrendImpressionIdFeature extends Feature[UnifiedTrendCandidate, Option[String]]
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD
deleted file mode 100644
index beb7ae2a9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/scala/com/twitter/search/common/util/bloomfilter",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/scala/com/twitter/search/common/util/bloomfilter",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala
deleted file mode 100644
index 647250ba0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.model.cursor
-
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.{
- CursorType => UrtCursorType
-}
-
-/**
- * Cursor model that may be used when cursoring over an ordered candidate source.
- *
- * @param initialSortIndex See [[UrtPipelineCursor]]
- * @param id represents the ID of the element, typically the top element for a top cursor or the
- * bottom element for a bottom cursor, in an ordered candidate list
- * @param gapBoundaryId represents the ID of the gap boundary element, which in gap cursors is the
- * opposite bound of the gap to be filled with the cursor
- */
-case class UrtOrderedCursor(
- override val initialSortIndex: Long,
- id: Option[Long],
- cursorType: Option[UrtCursorType],
- gapBoundaryId: Option[Long] = None)
- extends UrtPipelineCursor
-
-case class OrderedCursor(
- id: Option[Long],
- cursorType: Option[CursorType],
- gapBoundaryId: Option[Long] = None)
- extends PipelineCursor
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala
deleted file mode 100644
index 4b6c9bec2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.model.cursor
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.{
- CursorType => UrtCursorType
-}
-
-case object PreviousCursorFeature
- extends Feature[PipelineQuery with HasPipelineCursor[UrtPassThroughCursor], String]
-
-case object NextCursorFeature
- extends Feature[PipelineQuery with HasPipelineCursor[UrtPassThroughCursor], String]
-
-/**
- * Cursor model that may be used when we want to pass through the cursor value from and back to
- * a downstream as-is.
- *
- * @param initialSortIndex See [[UrtPipelineCursor]]
- * @param cursorValue the pass through cursor
- */
-case class UrtPassThroughCursor(
- override val initialSortIndex: Long,
- cursorValue: String,
- cursorType: Option[UrtCursorType] = None)
- extends UrtPipelineCursor
-
-case class PassThroughCursor(
- cursorValue: String,
- cursorType: Option[CursorType] = None)
- extends PipelineCursor
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala
deleted file mode 100644
index 1b988256c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.model.cursor
-
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilter
-
-/**
- * Cursor model that may be used when cursoring over a unordered candidate source. On each server
- * round-trip, the server will add the IDs of the candidates into a space efficient bloom filter.
- * Then on subsequent requests the client will return the cursor, and the bloom filter can be sent to
- * the downstream's bloom filter parameter in serialized form, or exclude candidates locally via a
- * filter on the candidate source pipeline.
- *
- * @param initialSortIndex See [[UrtPipelineCursor]]
- * @param longIntBloomFilter the bloom filter to use to dedup candidate from the candidate list
- */
-case class UrtUnorderedBloomFilterCursor(
- override val initialSortIndex: Long,
- // space-efficient and mutable variant of the BloomFilter class used for storing long integers.
- longIntBloomFilter: AdaptiveLongIntBloomFilter)
- extends UrtPipelineCursor
-
-case class UnorderedBloomFilterCursor(
- longIntBloomFilter: AdaptiveLongIntBloomFilter)
- extends PipelineCursor
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala
deleted file mode 100644
index bc3c4b83e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.model.cursor
-
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-
-/**
- * URT Cursor model that may be used when cursoring over a unordered candidate source. On each server
- * round-trip, the server will append the IDs of the elements in the response to the cursor. Then
- * on subsequent requests the client will return the cursor, and the excludedIds list can be sent to
- * the downstream's excludeIds parameter, or excluded locally via a filter on the candidate source
- * pipeline.
- *
- * Note that the cursor is bounded, as the excludedIds list cannot be appended to indefinitely due
- * to payload size constraints. As such, this strategy is typically used for bounded (limited page
- * size) products, or for unbounded (unlimited page size) products in conjunction with an
- * impression store. In the latter case, the cursor excludedIds list would be limited to a max size
- * via a circular buffer implementation, which would be unioned with the impression store IDs when
- * filtering. This usage allows the impression store to "catch up", as there is often latency
- * between when an impression client event is sent by the client and storage in the impression
- * store.
- *
- * @param initialSortIndex See [[UrtPipelineCursor]]
- * @param excludedIds the list of IDs to exclude from the candidate list
- */
-case class UrtUnorderedExcludeIdsCursor(
- override val initialSortIndex: Long,
- excludedIds: Seq[Long])
- extends UrtPipelineCursor
-
-case class UnorderedExcludeIdsCursor(excludedIds: Seq[Long]) extends PipelineCursor
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala
deleted file mode 100644
index aeb23de72..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.component_library.model.cursor
-
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-
-/**
- * Cursor model that may be used when we just need a placeholder but no real cursor value. Since URT
- * requires that top and bottom cursors are always present, placeholders are often used when up
- * scrolling (PTR) is not supported on a timeline. While placeholder cursors generally should not be
- * submitted back by the client, they sometimes are like in the case of client-side background
- * auto-refresh. If submitted, the backend will treat any request with a placeholder cursor like no
- * cursor was submitted, which will behave the same way as an initial page load.
- */
-case class UrtPlaceholderCursor() extends UrtPipelineCursor {
- // This value is unused, in that it is not serialized into the final cursor value
- override def initialSortIndex: Long = throw new UnsupportedOperationException(
- "initialSortIndex is not defined for placeholder cursors")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel
deleted file mode 100644
index 728bad076..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD
deleted file mode 100644
index 54b01577e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala
deleted file mode 100644
index f2128529b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.component_library.model.presentation.slice
-
-import com.twitter.product_mixer.core.model.common.presentation.slice.BaseSliceItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-
-case class SliceItemPresentation(override val sliceItem: SliceItem)
- extends BaseSliceItemPresentation
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD
deleted file mode 100644
index 062428d76..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala
deleted file mode 100644
index 732c7273e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.component_library.model.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation
-import com.twitter.product_mixer.core.model.common.presentation.urt.IsDispensable
-import com.twitter.product_mixer.core.model.common.presentation.urt.WithItemTreeDisplay
-
-trait ConversationModuleItem
- extends BaseUrtItemPresentation
- with IsDispensable
- with WithItemTreeDisplay
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala
deleted file mode 100644
index 9286ce4dd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.component_library.model.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-case class UrtItemPresentation(
- override val timelineItem: TimelineItem,
- override val modulePresentation: Option[BaseUrtModulePresentation] = None)
- extends BaseUrtItemPresentation
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala
deleted file mode 100644
index 5471d8a55..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.component_library.model.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-
-final case class UrtModulePresentation(
- override val timelineModule: TimelineModule)
- extends BaseUrtModulePresentation
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala
deleted file mode 100644
index cbfef0cb2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.component_library.model.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtOperationPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation
-
-final case class UrtOperationPresentation(
- override val timelineOperation: TimelineOperation)
- extends BaseUrtOperationPresentation
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala
deleted file mode 100644
index 5525d984a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.model.query.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.dspbidder.commons.{thriftscala => dsp}
-
-/**
- * AdsQuery holds request-time fields required by our ads candidate pipelines
- */
-trait AdsQuery {
-
- /**
- * Timelines-specific context.
- *
- * @note used in Home Timelines
- */
- def timelineRequestParams: Option[ads.TimelineRequestParams] = None
-
- /**
- * Navigation action trigger-type
- *
- * @note used in Home Timelines
- */
- def requestTriggerType: Option[ads.RequestTriggerType] = None
-
- /**
- * Autoplay setting
- *
- * @note used in Home Timelines
- */
- def autoplayEnabled: Option[Boolean] = None
-
- /**
- * Disable NSFW avoidance for ads mixing
- *
- * @note used in Home Timelines
- */
- def disableNsfwAvoidance: Option[Boolean] = None
-
- /**
- * DSP context for adwords
- *
- * @note used in Home Timelines
- */
- def dspClientContext: Option[dsp.DspClientContext] = None
-
- /**
- * User ID for the User Profile being viewed.
- *
- * @note used in Profile Timelines
- */
- def userProfileViewedUserId: Option[Long] = None
-
- /**
- * Search-specific context.
- *
- * @note used in Search Timelines
- */
- def searchRequestContext: Option[ads.SearchRequestContext] = None
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD
deleted file mode 100644
index eb9b9d5d0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "dspbidder/thrift/src/main/thrift/com/twitter/dspbidder/commons:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala",
- ],
- exports = [
- "dspbidder/thrift/src/main/thrift/com/twitter/dspbidder/commons:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala
deleted file mode 100644
index db100f9ed..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.annotations.Flags
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.account_recommendations_mixer.thriftscala.AccountRecommendationsMixer
-import com.twitter.util.Duration
-
-/**
- * Implementation with reasonable defaults for an idempotent Account Recommendations Mixer Thrift client.
- *
- * Note that the per request and total timeouts configured in this module are meant to represent a
- * reasonable starting point only. These were selected based on common practice, and should not be
- * assumed to be optimal for any particular use case. If you are interested in further tuning the
- * settings in this module, it is recommended to create local copy for your service.
- */
-object AccountRecommendationsMixerModule
- extends ThriftMethodBuilderClientModule[
- AccountRecommendationsMixer.ServicePerEndpoint,
- AccountRecommendationsMixer.MethodPerEndpoint
- ]
- with MtlsClient {
- final val AccountRecommendationsMixerTimeoutPerRequest =
- "account_recommendations_mixer.timeout_per_request"
- final val AccountRecommendationsMixerTimeoutTotal = "account_recommendations_mixer.timeout_total"
-
- flag[Duration](
- name = AccountRecommendationsMixerTimeoutPerRequest,
- default = 800.milliseconds,
- help = "Timeout per request for AccountRecommendationsMixer")
-
- flag[Duration](
- name = AccountRecommendationsMixerTimeoutTotal,
- default = 1200.milliseconds,
- help = "Timeout total for AccountRecommendationsMixer")
-
- override val label: String = "account-recs-mixer"
-
- override val dest: String = "/s/account-recs-mixer/account-recs-mixer:thrift"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- val timeOutPerRequest: Duration = injector
- .instance[Duration](Flags.named(AccountRecommendationsMixerTimeoutPerRequest))
- val timeOutTotal: Duration =
- injector.instance[Duration](Flags.named(AccountRecommendationsMixerTimeoutTotal))
- methodBuilder
- .withTimeoutPerRequest(timeOutPerRequest)
- .withTimeoutTotal(timeOutTotal)
- .idempotent(5.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD
deleted file mode 100644
index 020a0cc52..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD
+++ /dev/null
@@ -1,72 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala",
- "content-recommender/thrift/src/main/thrift:thrift-scala",
- "cr-mixer/thrift/src/main/thrift:thrift-scala",
- "decider/src/main/scala",
- "explore/explore-ranker/thrift/src/main/thrift:thrift-scala",
- "finagle/finagle-memcached/src/main/scala",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-thrift-client/src/main/scala",
- "finatra/utils/src/main/java/com/twitter/finatra/annotations",
- "follow-recommendations-service/thrift/src/main/thrift:thrift-scala",
- "home-scorer/thrift/src/main/thrift:thrift-scala",
- "interests_discovery/thrift/src/main/thrift:service-thrift-scala",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "people-discovery/api/thrift/src/main/thrift:thrift-scala",
- "src/scala/com/twitter/summingbird_internal/runner/store_config",
- "src/thrift/com/twitter/gizmoduck:thrift-scala",
- "src/thrift/com/twitter/search:earlybird-scala",
- "src/thrift/com/twitter/socialgraph:thrift-scala",
- "src/thrift/com/twitter/timelinemixer:thrift-scala",
- "src/thrift/com/twitter/timelineranker:thrift-scala",
- "src/thrift/com/twitter/timelines/impression_store:thrift-scala",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelineservice:thrift-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "stitch/stitch-gizmoduck",
- "stitch/stitch-socialgraph",
- "stitch/stitch-timelineservice/src/main/scala",
- "stitch/stitch-tweetypie",
- "timelines/src/main/scala/com/twitter/timelines/impressionstore/store",
- "tweetconvosvc/client/src/main/scala/com/twitter/tweetconvosvc/client/builder",
- "user_session_store/src/main/scala/com/twitter/user_session_store/config",
- "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readonly",
- "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readwrite",
- ],
- exports = [
- "3rdparty/src/jvm/com/twitter/storehaus:core",
- "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala",
- "content-recommender/thrift/src/main/thrift:thrift-scala",
- "finagle/finagle-memcached/src/main/scala",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-thrift-client/src/main/scala",
- "finatra/utils/src/main/java/com/twitter/finatra/annotations",
- "follow-recommendations-service/thrift/src/main/thrift:thrift-scala",
- "interests_discovery/thrift/src/main/thrift:service-thrift-scala",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "src/scala/com/twitter/summingbird_internal/runner/store_config",
- "src/thrift/com/twitter/gizmoduck:thrift-scala",
- "src/thrift/com/twitter/socialgraph:thrift-scala",
- "src/thrift/com/twitter/timelineranker:thrift-scala",
- "src/thrift/com/twitter/timelines/impression_store:thrift-scala",
- "src/thrift/com/twitter/tweetypie:service-scala",
- "stitch/stitch-gizmoduck",
- "stitch/stitch-socialgraph",
- "stitch/stitch-tweetypie",
- "timelines/src/main/scala/com/twitter/timelines/impressionstore/store",
- "user_session_store/src/main/scala/com/twitter/user_session_store/config",
- "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readonly",
- "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readwrite",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala
deleted file mode 100644
index dcba0279b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.ThriftMux
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.tweetconvosvc.thriftscala.ConversationService
-import com.twitter.util.Duration
-import org.apache.thrift.protocol.TCompactProtocol
-
-object ConversationServiceModule
- extends ThriftMethodBuilderClientModule[
- ConversationService.ServicePerEndpoint,
- ConversationService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label: String = "tweetconvosvc"
- override val dest: String = "/s/tweetconvosvc/tweetconvosvc"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder =
- methodBuilder
- .withTimeoutTotal(200.milliseconds)
- .withTimeoutPerRequest(100.milliseconds)
- .idempotent(1.percent)
-
- override def configureThriftMuxClient(
- injector: Injector,
- client: ThriftMux.Client
- ): ThriftMux.Client =
- super
- .configureThriftMuxClient(injector, client)
- .withProtocolFactory(new TCompactProtocol.Factory())
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala
deleted file mode 100644
index 8c09804bd..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.cr_mixer.{thriftscala => t}
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.util.Duration
-
-object CrMixerClientModule
- extends ThriftMethodBuilderClientModule[
- t.CrMixer.ServicePerEndpoint,
- t.CrMixer.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "cr-mixer"
- override val dest = "/s/cr-mixer/cr-mixer"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(500.millis)
- .withTimeoutTotal(750.millis)
- .idempotent(1.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala
deleted file mode 100644
index 94b446232..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.decider.Decider
-import com.twitter.decider.RandomRecipient
-import com.twitter.finagle.thrift.ClientId
-import com.twitter.finagle.thrift.service.Filterable
-import com.twitter.finagle.thrift.service.ReqRepServicePerEndpointBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.annotations.Flags
-import com.twitter.inject.thrift.modules.ReqRepDarkTrafficFilterModule
-import scala.reflect.ClassTag
-
-class DarkTrafficFilterModule[MethodIface <: Filterable[MethodIface]: ClassTag](
- implicit serviceBuilder: ReqRepServicePerEndpointBuilder[MethodIface])
- extends ReqRepDarkTrafficFilterModule
- with MtlsClient {
-
- override protected def enableSampling(injector: Injector): Any => Boolean = _ => {
- val decider = injector.instance[Decider]
- val deciderKey =
- injector.instance[String](Flags.named("thrift.dark.traffic.filter.decider_key"))
- val fromProxy = ClientId.current
- .map(_.name).exists(name => name.contains("diffy") || name.contains("darktraffic"))
- !fromProxy && decider.isAvailable(deciderKey, recipient = Some(RandomRecipient))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala
deleted file mode 100644
index 0be558201..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.ThriftMux
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.annotations.Flags
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.search.earlybird.{thriftscala => t}
-import com.twitter.util.Duration
-import org.apache.thrift.protocol.TCompactProtocol
-
-object EarlybirdModule
- extends ThriftMethodBuilderClientModule[
- t.EarlybirdService.ServicePerEndpoint,
- t.EarlybirdService.MethodPerEndpoint
- ]
- with MtlsClient {
- final val EarlybirdTimeoutPerRequest = "earlybird.timeout_per_request"
- final val EarlybirdTimeoutTotal = "earlybird.timeout_total"
-
- flag[Duration](
- name = EarlybirdTimeoutPerRequest,
- default = 200.milliseconds,
- help = "Timeout per request for Earlybird")
-
- flag[Duration](
- name = EarlybirdTimeoutTotal,
- default = 400.milliseconds,
- help = "Timeout total for Earlybird")
-
- override val dest = "/s/earlybird-root-superroot/root-superroot"
- override val label = "earlybird"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- val timeOutPerRequest: Duration = injector
- .instance[Duration](Flags.named(EarlybirdTimeoutPerRequest))
- val timeOutTotal: Duration = injector.instance[Duration](Flags.named(EarlybirdTimeoutTotal))
- methodBuilder
- // See TL-14313 for load testing details that led to 200ms being selected as request timeout
- .withTimeoutPerRequest(timeOutPerRequest)
- .withTimeoutTotal(timeOutTotal)
- .idempotent(5.percent)
- }
-
- override def configureThriftMuxClient(
- injector: Injector,
- client: ThriftMux.Client
- ): ThriftMux.Client =
- super
- .configureThriftMuxClient(injector, client)
- .withProtocolFactory(new TCompactProtocol.Factory())
-
- override protected def sessionAcquisitionTimeout: Duration = 1.seconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala
deleted file mode 100644
index b339eddce..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.explore_ranker.thriftscala.ExploreRanker
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.annotations.Flags
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.util.Duration
-
-object ExploreRankerClientModule
- extends ThriftMethodBuilderClientModule[
- ExploreRanker.ServicePerEndpoint,
- ExploreRanker.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label: String = "explore-ranker"
- override val dest: String = "/s/explore-ranker/explore-ranker"
-
- private final val ExploreRankerTimeoutTotal = "explore_ranker.timeout_total"
-
- flag[Duration](
- name = ExploreRankerTimeoutTotal,
- default = 800.milliseconds,
- help = "Timeout total for ExploreRanker")
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- val timeoutTotal: Duration = injector.instance[Duration](Flags.named(ExploreRankerTimeoutTotal))
- methodBuilder
- .withTimeoutTotal(timeoutTotal)
- .nonIdempotent
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala
deleted file mode 100644
index d394290b7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.follow_recommendations.thriftscala.FollowRecommendationsThriftService
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.util.Duration
-
-object FollowRecommenderServiceModule
- extends ThriftMethodBuilderClientModule[
- FollowRecommendationsThriftService.ServicePerEndpoint,
- FollowRecommendationsThriftService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label: String = "follow-recommendations-service"
-
- override val dest: String = "/s/follow-recommendations/follow-recos-service"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(400.millis)
- .withTimeoutTotal(800.millis)
- .idempotent(5.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala
deleted file mode 100644
index dc4e4afb8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.gizmoduck.thriftscala.UserService
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.stitch.gizmoduck.Gizmoduck
-import com.twitter.util.Duration
-import javax.inject.Singleton
-
-/**
- * Implementation with reasonable defaults for an idempotent Gizmoduck Thrift and Stitch client.
- *
- * Note that the per request and total timeouts configured in this module are meant to represent a
- * reasonable starting point only. These were selected based on common practice, and should not be
- * assumed to be optimal for any particular use case. If you are interested in further tuning the
- * settings in this module, it is recommended to create local copy for your service.
- */
-object GizmoduckClientModule
- extends ThriftMethodBuilderClientModule[
- UserService.ServicePerEndpoint,
- UserService.MethodPerEndpoint
- ]
- with MtlsClient {
- override val label: String = "gizmoduck"
- override val dest: String = "/s/gizmoduck/gizmoduck"
-
- @Singleton
- @Provides
- def provideGizmoduckStitchClient(userService: UserService.MethodPerEndpoint): Gizmoduck =
- new Gizmoduck(userService)
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder =
- methodBuilder
- .withTimeoutPerRequest(200.milliseconds)
- .withTimeoutTotal(400.milliseconds)
- .idempotent(1.percent)
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala
deleted file mode 100644
index 16823deb6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.home_scorer.{thriftscala => t}
-import com.twitter.util.Duration
-
-object HomeScorerClientModule
- extends ThriftMethodBuilderClientModule[
- t.HomeScorer.ServicePerEndpoint,
- t.HomeScorer.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "home-scorer"
- override val dest = "/s/home-scorer/home-scorer"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(1200.millis)
- .withTimeoutTotal(2400.millis)
- .idempotent(1.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala
deleted file mode 100644
index f4a5d211d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.interests_discovery.thriftscala.InterestsDiscoveryService
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.util.Duration
-
-object InterestsDiscoveryServiceModule
- extends ThriftMethodBuilderClientModule[
- InterestsDiscoveryService.ServicePerEndpoint,
- InterestsDiscoveryService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label: String = "interests-discovery-service"
-
- override val dest: String = "/s/interests_discovery/interests_discovery"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(500.millis)
- .withTimeoutTotal(1000.millis)
- .idempotent(5.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala
deleted file mode 100644
index fd564eb9f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.onboarding.task.service.thriftscala.TaskService
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.util.Duration
-import com.twitter.conversions.DurationOps._
-
-object OnboardingTaskServiceModule
- extends ThriftMethodBuilderClientModule[
- TaskService.ServicePerEndpoint,
- TaskService.MethodPerEndpoint
- ]
- with MtlsClient {
- override val label: String = "onboarding-task-service"
- override val dest: String = "/s/onboarding-task-service/onboarding-task-service"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(500.millis)
- .withTimeoutTotal(1000.millis)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala
deleted file mode 100644
index c9c1ab7a7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.peoplediscovery.api.thriftscala.ThriftPeopleDiscoveryService
-import com.twitter.util.Duration
-
-/**
- * Implementation with reasonable defaults for an idempotent People Discovery Thrift client.
- *
- * Note that the per request and total timeouts configured in this module are meant to represent a
- * reasonable starting point only. These were selected based on common practice, and should not be
- * assumed to be optimal for any particular use case. If you are interested in further tuning the
- * settings in this module, it is recommended to create local copy for your service.
- */
-object PeopleDiscoveryServiceModule
- extends ThriftMethodBuilderClientModule[
- ThriftPeopleDiscoveryService.ServicePerEndpoint,
- ThriftPeopleDiscoveryService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label: String = "people-discovery-api"
-
- override val dest: String = "/s/people-discovery-api/people-discovery-api:thrift"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(800.millis)
- .withTimeoutTotal(1200.millis)
- .idempotent(5.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala
deleted file mode 100644
index a37531260..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.socialgraph.thriftscala.SocialGraphService
-import com.twitter.stitch.socialgraph.SocialGraph
-import javax.inject.Singleton
-
-object SocialGraphServiceModule
- extends ThriftMethodBuilderClientModule[
- SocialGraphService.ServicePerEndpoint,
- SocialGraphService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- val label: String = "socialgraphservice"
- val dest: String = "/s/socialgraph/socialgraph"
-
- @Singleton
- @Provides
- def provideGizmoduckStitchClient(
- socialGraphService: SocialGraphService.MethodPerEndpoint
- ): SocialGraph =
- new SocialGraph(socialGraphService)
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder.withTimeoutPerRequest(400.millis)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala
deleted file mode 100644
index d36d2dfd7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.timelinemixer.{thriftscala => t}
-import com.twitter.util.Duration
-
-object TimelineMixerClientModule
- extends ThriftMethodBuilderClientModule[
- t.TimelineMixer.ServicePerEndpoint,
- t.TimelineMixer.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "timeline-mixer"
- override val dest = "/s/timelinemixer/timelinemixer"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(2000.millis)
- .withTimeoutTotal(4000.millis)
- .idempotent(1.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala
deleted file mode 100644
index 3a28cb3d1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.ThriftMux
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.mtls.client.MtlsStackClient._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.timelineranker.{thriftscala => t}
-import com.twitter.util.Duration
-import org.apache.thrift.protocol.TCompactProtocol
-
-object TimelineRankerClientModule
- extends ThriftMethodBuilderClientModule[
- t.TimelineRanker.ServicePerEndpoint,
- t.TimelineRanker.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "timeline-ranker"
- override val dest = "/s/timelineranker/timelineranker:compactthrift"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(750.millis)
- .withTimeoutTotal(750.millis)
- }
-
- override def configureThriftMuxClient(
- injector: Injector,
- client: ThriftMux.Client
- ): ThriftMux.Client = {
- val serviceIdentifier = injector.instance[ServiceIdentifier]
- super
- .configureThriftMuxClient(injector, client)
- .withProtocolFactory(new TCompactProtocol.Factory())
- .withMutualTls(serviceIdentifier)
- .withPerEndpointStats
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala
deleted file mode 100644
index 32310303b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.timelinescorer.{thriftscala => t}
-import com.twitter.util.Duration
-
-object TimelineScorerClientModule
- extends ThriftMethodBuilderClientModule[
- t.TimelineScorer.ServicePerEndpoint,
- t.TimelineScorer.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "timeline-scorer"
- override val dest = "/s/timelinescorer/timelinescorer"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(2000.millis)
- .withTimeoutTotal(4000.millis)
- .idempotent(1.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala
deleted file mode 100644
index 115136fdb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.stitch.timelineservice.TimelineService
-import com.twitter.timelineservice.{thriftscala => t}
-import com.twitter.util.Duration
-import javax.inject.Singleton
-
-object TimelineServiceClientModule
- extends ThriftMethodBuilderClientModule[
- t.TimelineService.ServicePerEndpoint,
- t.TimelineService.MethodPerEndpoint
- ]
- with MtlsClient {
-
- override val label = "timelineservice"
- override val dest = "/s/timelineservice/timelineservice"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutPerRequest(1200.millis)
- .withTimeoutTotal(2400.millis)
- .idempotent(1.percent)
- }
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-
- @Singleton
- @Provides
- def providesTimelineServiceStitchClient(
- client: t.TimelineService.MethodPerEndpoint
- ): TimelineService = {
- new TimelineService(client)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala
deleted file mode 100644
index 3929a1437..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.Memcached
-import com.twitter.finagle.Resolver
-import com.twitter.finagle.memcached.protocol.Command
-import com.twitter.finagle.memcached.protocol.Response
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.mtls.client.MtlsStackClient._
-import com.twitter.finagle.param.HighResTimer
-import com.twitter.finagle.service.RetryExceptionsFilter
-import com.twitter.finagle.service.RetryPolicy
-import com.twitter.finagle.service.StatsFilter
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.storehaus.ReadableStore
-import com.twitter.timelines.impressionstore.store.TweetImpressionsStore
-import com.twitter.timelines.impressionstore.thriftscala.ImpressionList
-import javax.inject.Singleton
-
-object TweetImpressionStoreModule extends TwitterModule {
- private val TweetImpressionMemcacheWilyPath = "/s/cache/timelines_impressionstore:twemcaches"
- private val tweetImpressionLabel = "timelinesTweetImpressions"
-
- @Provides
- @Singleton
- def provideTimelineTweetImpressionStore(
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): ReadableStore[Long, ImpressionList] = {
- val scopedStatsReceiver = statsReceiver.scope("timelinesTweetImpressions")
-
- // the below values for configuring the Memcached client
- // are set to be the same as Home timeline's read path to the impression store.
- val acquisitionTimeoutMillis = 200.milliseconds
- val requestTimeoutMillis = 300.milliseconds
- val numTries = 2
-
- val statsFilter = new StatsFilter[Command, Response](scopedStatsReceiver)
- val retryFilter = new RetryExceptionsFilter[Command, Response](
- retryPolicy = RetryPolicy.tries(
- numTries,
- RetryPolicy.TimeoutAndWriteExceptionsOnly
- .orElse(RetryPolicy.ChannelClosedExceptionsOnly)
- ),
- timer = HighResTimer.Default,
- statsReceiver = scopedStatsReceiver
- )
-
- val client = Memcached.client
- .withMutualTls(serviceIdentifier)
- .withSession
- .acquisitionTimeout(acquisitionTimeoutMillis)
- .withRequestTimeout(requestTimeoutMillis)
- .withStatsReceiver(scopedStatsReceiver)
- .filtered(statsFilter.andThen(retryFilter))
- .newRichClient(
- dest = Resolver.eval(TweetImpressionMemcacheWilyPath),
- label = tweetImpressionLabel
- )
-
- TweetImpressionsStore.tweetImpressionsStore(client)
- }
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala
deleted file mode 100644
index f2d2a59c0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.PercentOps._
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.thrift.ClientId
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.stitch.tweetypie.TweetyPie
-import com.twitter.tweetypie.thriftscala.TweetService
-import com.twitter.util.Duration
-import javax.inject.Singleton
-
-/**
- * Implementation with reasonable defaults for an idempotent TweetyPie Thrift and Stitch client.
- *
- * Note that the per request and total timeouts are meant to represent a reasonable starting point
- * only. These were selected based on common practice, and should not be assumed to be optimal for
- * any particular use case. If you are interested in further tuning the settings in this module,
- * it is recommended to create local copy for your service.
- */
-object TweetyPieClientModule
- extends ThriftMethodBuilderClientModule[
- TweetService.ServicePerEndpoint,
- TweetService.MethodPerEndpoint
- ]
- with MtlsClient {
- override val label: String = "tweetypie"
- override val dest: String = "/s/tweetypie/tweetypie"
-
- @Singleton
- @Provides
- def providesTweetypieStitchClient(tweetService: TweetService.MethodPerEndpoint): TweetyPie =
- new TweetyPie(tweetService)
-
- /**
- * TweetyPie client id must be in the form of {service.env} or it will not be treated as an
- * unauthorized client
- */
- override protected def clientId(injector: Injector): ClientId = {
- val serviceIdentifier = injector.instance[ServiceIdentifier]
- ClientId(s"${serviceIdentifier.service}.${serviceIdentifier.environment}")
- }
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder =
- methodBuilder
- .withTimeoutPerRequest(200.milliseconds)
- .withTimeoutTotal(400.milliseconds)
- .idempotent(1.percent)
-
- override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala
deleted file mode 100644
index 4c1d983ca..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.component_library.module
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.user_session_store.ReadOnlyUserSessionStore
-import com.twitter.user_session_store.ReadWriteUserSessionStore
-import com.twitter.user_session_store.UserSessionDataset
-import com.twitter.user_session_store.UserSessionDataset.UserSessionDataset
-import com.twitter.user_session_store.config.manhattan.UserSessionStoreManhattanConfig
-import com.twitter.user_session_store.impl.manhattan.readonly.ReadOnlyManhattanUserSessionStoreBuilder
-import com.twitter.user_session_store.impl.manhattan.readwrite.ReadWriteManhattanUserSessionStoreBuilder
-
-import javax.inject.Singleton
-
-object UserSessionStoreModule extends TwitterModule {
- private val ReadWriteAppId = "timelineservice_user_session_store"
- private val ReadWriteStagingDataset = "tls_user_session_store_nonprod"
- private val ReadWriteProdDataset = "tls_user_session_store"
- private val ReadOnlyAppId = "user_session_store"
- private val ReadOnlyDataset = "user_session_fields"
-
- @Provides
- @Singleton
- def providesReadWriteUserSessionStore(
- injectedServiceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): ReadWriteUserSessionStore = {
- val scopedStatsReceiver = statsReceiver.scope(injectedServiceIdentifier.service)
-
- val dataset = injectedServiceIdentifier.environment.toLowerCase match {
- case "prod" => ReadWriteProdDataset
- case _ => ReadWriteStagingDataset
- }
-
- val clientReadWriteConfig = new UserSessionStoreManhattanConfig.Prod.ReadWrite.Omega {
- override val appId = ReadWriteAppId
- override val defaultMaxTimeout = 400.milliseconds
- override val maxRetryCount = 1
- override val serviceIdentifier = injectedServiceIdentifier
- override val datasetNamesById = Map[UserSessionDataset, String](
- UserSessionDataset.ActiveDaysInfo -> dataset,
- UserSessionDataset.NonPollingTimes -> dataset
- )
- }
-
- ReadWriteManhattanUserSessionStoreBuilder
- .buildReadWriteUserSessionStore(clientReadWriteConfig, statsReceiver, scopedStatsReceiver)
- }
-
- @Provides
- @Singleton
- def providesReadOnlyUserSessionStore(
- injectedServiceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): ReadOnlyUserSessionStore = {
- val scopedStatsReceiver = statsReceiver.scope(injectedServiceIdentifier.service)
-
- val clientReadOnlyConfig = new UserSessionStoreManhattanConfig.Prod.ReadOnly.Athena {
- override val appId = ReadOnlyAppId
- override val defaultMaxTimeout = 400.milliseconds
- override val maxRetryCount = 1
- override val serviceIdentifier = injectedServiceIdentifier
- override val datasetNamesById = Map[UserSessionDataset, String](
- UserSessionDataset.UserHealth -> ReadOnlyDataset
- )
- }
-
- ReadOnlyManhattanUserSessionStoreBuilder
- .buildReadOnlyUserSessionStore(clientReadOnlyConfig, statsReceiver, scopedStatsReceiver)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel
deleted file mode 100644
index 16d3773f0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "cr-ml-ranker/thrift/src/main/thrift:thrift-scala",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala
deleted file mode 100644
index 8c18d31b4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.module.cr_ml_ranker
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.cr_ml_ranker.thriftscala.CrMLRanker
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient
-import com.twitter.inject.Injector
-import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule
-import com.twitter.product_mixer.component_library.scorer.cr_ml_ranker.CrMlRankerScoreStitchClient
-import com.twitter.util.Duration
-import javax.inject.Singleton
-
-case class CrMLRankerModule(totalTimeout: Duration = 100.milliseconds, batchSize: Int = 50)
- extends ThriftMethodBuilderClientModule[
- CrMLRanker.ServicePerEndpoint,
- CrMLRanker.MethodPerEndpoint
- ]
- with MtlsClient {
- override val label = "cr-ml-ranker"
- override val dest = "/s/cr-ml-ranker/cr-ml-ranker"
-
- override protected def configureMethodBuilder(
- injector: Injector,
- methodBuilder: MethodBuilder
- ): MethodBuilder = {
- methodBuilder
- .withTimeoutTotal(totalTimeout)
- }
-
- @Provides
- @Singleton
- def providesStitchClient(
- crMlRankerThriftClient: CrMLRanker.MethodPerEndpoint
- ): CrMlRankerScoreStitchClient = new CrMlRankerScoreStitchClient(
- crMlRankerThriftClient,
- maxBatchSize = batchSize
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD
deleted file mode 100644
index 2f6ec6310..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/http-client/src/main/scala",
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client",
- "util/util-core:scala",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- "util/util-security/src/main/scala/com/twitter/util/security",
- ],
- exports = [
- "finagle/finagle-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/http-client/src/main/scala",
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client",
- "util/util-core:scala",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- "util/util-security/src/main/scala/com/twitter/util/security",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala
deleted file mode 100644
index 1f75ec99a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.Http
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClientMutualTls
-import com.twitter.util.Duration
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinagleHttpClientModule extends TwitterModule {
-
- final val HttpClientRequestTimeout = "http_client.request_timeout"
- final val HttpClientConnectTimeout = "http_client.connect_timeout"
- final val HttpClientAcquisitionTimeout = "http_client.acquisition_timeout"
-
- flag[Duration](
- name = HttpClientRequestTimeout,
- default = 200.milliseconds,
- help = "HTTP client request timeout")
-
- flag[Duration](
- name = HttpClientConnectTimeout,
- default = 500.milliseconds,
- help = "HTTP client transport connect timeout")
-
- flag[Duration](
- name = HttpClientAcquisitionTimeout,
- default = 500.milliseconds,
- help = "HTTP client session acquisition timeout")
-
- final val FinagleHttpClientModule = "FinagleHttpClientModule"
-
- /**
- * Provides a Finagle HTTP client with S2S Auth / Mutual TLS
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP Client with S2S Auth / Mutual TLS
- */
- @Provides
- @Singleton
- @Named(FinagleHttpClientModule)
- def providesFinagleHttpClient(
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): Http.Client =
- buildFinagleHttpClientMutualTls(
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- serviceIdentifier = serviceIdentifier,
- statsReceiver = statsReceiver
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala
deleted file mode 100644
index 9ea2a7bb7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.Http
-import com.twitter.finagle.http.ProxyCredentials
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithCredentialProxy
-import com.twitter.product_mixer.shared_library.http_client.HttpHostPort
-import com.twitter.util.Duration
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinagleHttpClientWithCredentialProxyModule extends TwitterModule {
-
- final val FinagleHttpClientWithCredentialProxy = "FinagleHttpClientWithCredentialProxy"
-
- /**
- * Provide a Finagle HTTP client with Egress Proxy support using Credentials
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param proxyTwitterHost Twitter egress proxy host
- * @param proxyTwitterPort Twitter egress proxy port
- * @param proxyRemoteHost Remote proxy host
- * @param proxyRemotePort Remote proxy port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param isServiceLocal If this is a Local deployment for testing
- * @param proxyCredentials Proxy credentials
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP client with Egress Proxy support using Credentials
- */
- @Provides
- @Singleton
- @Named(FinagleHttpClientWithCredentialProxy)
- def providesFinagleHttpClientWithCredentialProxy(
- @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String,
- @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int,
- @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String,
- @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int,
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- proxyCredentials: ProxyCredentials,
- statsReceiver: StatsReceiver
- ): Http.Client = {
-
- val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort)
- val remoteProxyHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort)
-
- buildFinagleHttpClientWithCredentialProxy(
- twitterProxyHostPort = twitterProxyHostPort,
- remoteProxyHostPort = remoteProxyHostPort,
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- proxyCredentials = proxyCredentials,
- statsReceiver = statsReceiver
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala
deleted file mode 100644
index c169d7fed..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.Http
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithProxy
-import com.twitter.product_mixer.shared_library.http_client.HttpHostPort
-import com.twitter.util.Duration
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinagleHttpClientWithProxyModule extends TwitterModule {
- final val HttpClientWithProxyTwitterHost = "http_client.proxy.twitter_host"
- final val HttpClientWithProxyTwitterPort = "http_client.proxy.twitter_port"
- final val HttpClientWithProxyRemoteHost = "http_client.proxy.remote_host"
- final val HttpClientWithProxyRemotePort = "http_client.proxy.remote_port"
-
- flag[String](
- HttpClientWithProxyTwitterHost,
- "httpproxy.local.twitter.com",
- "Twitter egress proxy host")
-
- flag[Int](HttpClientWithProxyTwitterPort, 3128, "Twitter egress proxy port")
-
- flag[String](HttpClientWithProxyRemoteHost, "Host that the proxy will connect to")
-
- flag[Int](HttpClientWithProxyRemotePort, 443, "Port that the proxy will connect to")
-
- final val FinagleHttpClientWithProxy = "FinagleHttpClientWithProxy"
-
- /**
- * Provide a Finagle HTTP client with Egress Proxy support
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param proxyTwitterHost Twitter egress proxy host
- * @param proxyTwitterPort Twitter egress proxy port
- * @param proxyRemoteHost Remote proxy host
- * @param proxyRemotePort Remote proxy port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param isServiceLocal If this is a Local deployment for testing
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP client with Egress Proxy support
- */
- @Provides
- @Singleton
- @Named(FinagleHttpClientWithProxy)
- def providesFinagleHttpClientWithProxy(
- @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String,
- @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int,
- @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String,
- @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int,
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- statsReceiver: StatsReceiver
- ): Http.Client = {
- val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort)
- val remoteProxyHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort)
-
- buildFinagleHttpClientWithProxy(
- twitterProxyHostPort = twitterProxyHostPort,
- remoteProxyHostPort = remoteProxyHostPort,
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- statsReceiver = statsReceiver
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala
deleted file mode 100644
index 3e68b0477..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finatra.httpclient.HttpClient
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClientMutualTls
-import com.twitter.product_mixer.shared_library.http_client.HttpHostPort
-import com.twitter.util.Duration
-import com.twitter.util.jackson.ScalaObjectMapper
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinatraHttpClientModule extends TwitterModule {
-
- final val HttpClientHost = "http_client.host"
- final val HttpClientPort = "http_client.port"
-
- flag[String](HttpClientHost, "Host that the client will connect to")
-
- flag[Int](HttpClientPort, 443, "Port that the client will connect to")
-
- final val FinatraHttpClient = "FinatraHttpClient"
-
- /**
- * Build a Finatra HTTP client for a host. The Finatra HTTP client can be helpful (as opposed to
- * the base Finagle HTTP Client), as it provides built-in JSON response parsing and other
- * convenience methods
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param host Host to build Finatra client
- * @param port Port to build Finatra client
- * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param statsReceiver Stats
- *
- * @return Finatra HTTP client
- */
- @Provides
- @Singleton
- @Named(FinatraHttpClient)
- def providesFinatraHttpClient(
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- @Flag(HttpClientHost) host: String,
- @Flag(HttpClientPort) port: Int,
- scalaObjectMapper: ScalaObjectMapper,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): HttpClient = {
- val finagleHttpClient = buildFinagleHttpClientMutualTls(
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- serviceIdentifier = serviceIdentifier,
- statsReceiver = statsReceiver
- )
-
- val hostPort = HttpHostPort(host, port)
- val finagleHttpService = finagleHttpClient.newService(hostPort.toString)
-
- new HttpClient(
- hostname = hostPort.host,
- httpService = finagleHttpService,
- mapper = scalaObjectMapper
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala
deleted file mode 100644
index d3d2a7576..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.http.ProxyCredentials
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finatra.httpclient.HttpClient
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithCredentialProxy
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpServiceWithProxy
-import com.twitter.product_mixer.shared_library.http_client.HttpHostPort
-import com.twitter.util.Duration
-import com.twitter.util.jackson.ScalaObjectMapper
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinatraHttpClientWithCredentialProxyModule extends TwitterModule {
-
- final val FinatraHttpClientWithCredentialProxy = "FinagleHttpClientWithCredentialProxy"
-
- /**
- * Build a Finatra HTTP client with Egress Proxy support with Credentials for a host. The Finatra
- * HTTP client can be helpful (as opposed to the base Finagle HTTP Client), as it provides
- * built-in JSON response zparsing and other convenience methods
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param proxyTwitterHost Twitter egress proxy host
- * @param proxyTwitterPort Twitter egress proxy port
- * @param proxyRemoteHost Remote proxy host
- * @param proxyRemotePort Remote proxy port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param isServiceLocal Local deployment for testing
- * @param proxyCredentials Proxy credentials
- * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing
- * @param statsReceiver Stats
- *
- * @return Finatra HTTP client with Egress Proxy support for a host
- */
- @Provides
- @Singleton
- @Named(FinatraHttpClientWithCredentialProxy)
- def providesFinatraHttpClientWithCredentialProxy(
- @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String,
- @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int,
- @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String,
- @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int,
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- proxyCredentials: ProxyCredentials,
- scalaObjectMapper: ScalaObjectMapper,
- statsReceiver: StatsReceiver
- ): HttpClient = {
- val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort)
- val proxyRemoteHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort)
-
- val finagleHttpClientWithCredentialProxy =
- buildFinagleHttpClientWithCredentialProxy(
- twitterProxyHostPort = twitterProxyHostPort,
- remoteProxyHostPort = proxyRemoteHostPort,
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- proxyCredentials = proxyCredentials,
- statsReceiver = statsReceiver
- )
-
- val finagleHttpServiceWithCredentialProxy =
- buildFinagleHttpServiceWithProxy(
- finagleHttpClientWithProxy = finagleHttpClientWithCredentialProxy,
- twitterProxyHostPort = twitterProxyHostPort
- )
-
- new HttpClient(
- hostname = twitterProxyHostPort.host,
- httpService = finagleHttpServiceWithCredentialProxy,
- mapper = scalaObjectMapper
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala
deleted file mode 100644
index 1876acc88..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finatra.httpclient.HttpClient
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithProxy
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpServiceWithProxy
-import com.twitter.product_mixer.shared_library.http_client.HttpHostPort
-import com.twitter.util.Duration
-import com.twitter.util.jackson.ScalaObjectMapper
-import javax.inject.Named
-import javax.inject.Singleton
-
-object FinatraHttpClientWithProxyModule extends TwitterModule {
-
- final val FinatraHttpClientWithProxy = "FinagleHttpClientWithProxy"
-
- /**
- * Build a Finatra HTTP client with Egress Proxy support for a host. The Finatra HTTP client can
- * be helpful (as opposed to the base Finagle HTTP Client), as it provides built-in JSON response
- * parsing and other convenience methods
- *
- * Note that the timeouts configured in this module are meant to be a reasonable starting point
- * only. To further tuning the settings, either override the flags or create local copy of the module.
- *
- * @param proxyTwitterHost Twitter egress proxy host
- * @param proxyTwitterPort Twitter egress proxy port
- * @param proxyRemoteHost Remote proxy host
- * @param proxyRemotePort Remote proxy port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param isServiceLocal Local deployment for testing
- * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing
- * @param statsReceiver Stats
- *
- * @return Finatra HTTP client with Egress Proxy support for a host
- */
- @Provides
- @Singleton
- @Named(FinatraHttpClientWithProxy)
- def providesFinatraHttpClientWithProxy(
- @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String,
- @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int,
- @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String,
- @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int,
- @Flag(HttpClientRequestTimeout) requestTimeout: Duration,
- @Flag(HttpClientConnectTimeout) connectTimeout: Duration,
- @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- scalaObjectMapper: ScalaObjectMapper,
- statsReceiver: StatsReceiver
- ): HttpClient = {
- val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort)
- val proxyRemoteHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort)
-
- val finagleHttpClientWithProxy =
- buildFinagleHttpClientWithProxy(
- twitterProxyHostPort = twitterProxyHostPort,
- remoteProxyHostPort = proxyRemoteHostPort,
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- statsReceiver = statsReceiver
- )
-
- val finagleHttpServiceWithProxy =
- buildFinagleHttpServiceWithProxy(
- finagleHttpClientWithProxy = finagleHttpClientWithProxy,
- twitterProxyHostPort = twitterProxyHostPort
- )
-
- new HttpClient(
- hostname = twitterProxyHostPort.host,
- httpService = finagleHttpServiceWithProxy,
- mapper = scalaObjectMapper
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala
deleted file mode 100644
index 88cb81ce6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.component_library.module.http
-
-import com.google.inject.Provides
-import com.twitter.finagle.http.ProxyCredentials
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.util.security.{Credentials => CredentialsUtil}
-import java.io.File
-import javax.inject.Singleton
-
-object ProxyCredentialsModule extends TwitterModule {
- final val HttpClientWithProxyCredentialsPath = "http_client.proxy.proxy_credentials_path"
-
- flag[String](HttpClientWithProxyCredentialsPath, "", "Path the load the proxy credentials")
-
- @Provides
- @Singleton
- def providesProxyCredentials(
- @Flag(HttpClientWithProxyCredentialsPath) proxyCredentialsPath: String,
- ): ProxyCredentials = {
- val credentialsFile = new File(proxyCredentialsPath)
- ProxyCredentials(CredentialsUtil(credentialsFile))
- .getOrElse(throw MissingProxyCredentialsException)
- }
-
- object MissingProxyCredentialsException extends Exception("Proxy Credentials not found")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala
deleted file mode 100644
index d38bdff77..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-
-class AdsCandidatePipelineConfig[Query <: PipelineQuery with AdsQuery] @Inject() (
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- override val gates: Seq[Gate[Query]],
- override val candidateSource: CandidateSource[
- ads.AdRequestParams,
- ads.AdImpression
- ],
- override val filters: Seq[Filter[Query, AdsCandidate]],
- override val postFilterFeatureHydration: Seq[
- BaseCandidateFeatureHydrator[Query, AdsCandidate, _]
- ],
- override val decorator: Option[CandidateDecorator[Query, AdsCandidate]],
- override val alerts: Seq[Alert],
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- estimateNumOrganicItems: EstimateNumOrganicItems[Query],
- urtRequest: Option[Boolean],
-) extends CandidatePipelineConfig[
- Query,
- ads.AdRequestParams,
- ads.AdImpression,
- AdsCandidate
- ] {
-
- override val queryTransformer: CandidatePipelineQueryTransformer[Query, ads.AdRequestParams] =
- AdsCandidatePipelineQueryTransformer(
- adsDisplayLocationBuilder = adsDisplayLocationBuilder,
- estimatedNumOrganicItems = estimateNumOrganicItems,
- urtRequest = urtRequest)
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- ads.AdImpression,
- AdsCandidate
- ] = AdsCandidatePipelineResultsTransformer
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index c4a1ee6a3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.adserver.thriftscala.AdRequestParams
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad.AdsCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsCandidatePipelineConfigBuilder @Inject() () {
-
- def build[Query <: PipelineQuery with AdsQuery](
- adsCandidateSource: CandidateSource[AdRequestParams, AdImpression],
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- estimateNumOrganicItems: EstimateNumOrganicItems[Query],
- identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("Ads"),
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- gates: Seq[Gate[Query]] = Seq.empty,
- filters: Seq[Filter[Query, AdsCandidate]] = Seq.empty,
- postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, AdsCandidate, _]] =
- Seq.empty,
- decorator: Option[CandidateDecorator[Query, AdsCandidate]] =
- Some(UrtItemCandidateDecorator(AdsCandidateUrtItemBuilder())),
- alerts: Seq[Alert] = Seq.empty,
- urtRequest: Option[Boolean] = None,
- ): AdsCandidatePipelineConfig[Query] = {
- new AdsCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- gates = gates,
- candidateSource = adsCandidateSource,
- filters = filters,
- postFilterFeatureHydration = postFilterFeatureHydration,
- decorator = decorator,
- alerts = alerts,
- adsDisplayLocationBuilder = adsDisplayLocationBuilder,
- estimateNumOrganicItems = estimateNumOrganicItems,
- urtRequest = urtRequest,
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala
deleted file mode 100644
index 4669a6d0a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.component_library.pipeline.candidate.ads.AdsCandidatePipelineQueryTransformer.buildAdRequestParams
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Transform a PipelineQuery with AdsQuery into an AdsRequestParams
- *
- * @param adsDisplayLocationBuilder Builder that determines the display location for the ads
- * @param estimatedNumOrganicItems Estimate for the number of organic items that will be served
- * alongside inorganic items such as ads.
- */
-case class AdsCandidatePipelineQueryTransformer[Query <: PipelineQuery with AdsQuery](
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- estimatedNumOrganicItems: EstimateNumOrganicItems[Query],
- urtRequest: Option[Boolean],
-) extends CandidatePipelineQueryTransformer[Query, ads.AdRequestParams] {
-
- override def transform(query: Query): ads.AdRequestParams =
- buildAdRequestParams(
- query = query,
- adsDisplayLocation = adsDisplayLocationBuilder(query),
- organicItemIds = None,
- numOrganicItems = Some(estimatedNumOrganicItems(query)),
- urtRequest = urtRequest
- )
-}
-
-object AdsCandidatePipelineQueryTransformer {
-
- def buildAdRequestParams(
- query: PipelineQuery with AdsQuery,
- adsDisplayLocation: ads.DisplayLocation,
- organicItemIds: Option[Seq[Long]],
- numOrganicItems: Option[Short],
- urtRequest: Option[Boolean],
- ): ads.AdRequestParams = {
- val searchRequestContext = query.searchRequestContext
- val queryString = query.searchRequestContext.flatMap(_.queryString)
-
- val adRequest = ads.AdRequest(
- queryString = queryString,
- displayLocation = adsDisplayLocation,
- searchRequestContext = searchRequestContext,
- organicItemIds = organicItemIds,
- numOrganicItems = numOrganicItems,
- profileUserId = query.userProfileViewedUserId,
- isDebug = Some(false),
- isTest = Some(false),
- requestTriggerType = query.requestTriggerType,
- disableNsfwAvoidance = query.disableNsfwAvoidance,
- timelineRequestParams = query.timelineRequestParams,
- )
-
- val context = query.clientContext
-
- val clientInfo = ads.ClientInfo(
- clientId = context.appId.map(_.toInt),
- userId64 = context.userId,
- userIp = context.ipAddress,
- guestId = context.guestIdAds,
- userAgent = context.userAgent,
- deviceId = context.deviceId,
- languageCode = context.languageCode,
- countryCode = context.countryCode,
- mobileDeviceId = context.mobileDeviceId,
- mobileDeviceAdId = context.mobileDeviceAdId,
- limitAdTracking = context.limitAdTracking,
- autoplayEnabled = query.autoplayEnabled,
- urtRequest = urtRequest,
- dspClientContext = query.dspClientContext
- )
-
- ads.AdRequestParams(adRequest, clientInfo)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala
deleted file mode 100644
index ea693f800..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult
-
-object AdsCandidatePipelineResultsTransformer
- extends CandidatePipelineResultsTransformer[AdImpression, AdsCandidate] {
-
- override def transform(sourceResult: AdImpression): AdsCandidate =
- (sourceResult.nativeRtbCreative, sourceResult.promotedTweetId) match {
- case (None, Some(promotedTweetId)) =>
- AdsTweetCandidate(
- id = promotedTweetId,
- adImpression = sourceResult
- )
- case (Some(_), None) =>
- throw unsupportedAdImpressionPipelineFailure(
- impression = sourceResult,
- reason = "Received ad impression with rtbCreative")
- case (Some(_), Some(_)) =>
- throw unsupportedAdImpressionPipelineFailure(
- impression = sourceResult,
- reason = "Received ad impression with both rtbCreative and promoted tweetId")
- case (None, None) =>
- throw unsupportedAdImpressionPipelineFailure(
- impression = sourceResult,
- reason = "Received ad impression with neither rtbCreative nor promoted tweetId")
- }
-
- private def unsupportedAdImpressionPipelineFailure(impression: AdImpression, reason: String) =
- PipelineFailure(
- UnexpectedCandidateResult,
- reason =
- s"Unsupported AdImpression ($reason). impressionString: ${impression.impressionString}")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala
deleted file mode 100644
index 2df599613..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.DependentCandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-class AdsDependentCandidatePipelineConfig[Query <: PipelineQuery with AdsQuery](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- override val gates: Seq[BaseGate[Query]],
- override val candidateSource: CandidateSource[
- ads.AdRequestParams,
- ads.AdImpression
- ],
- override val filters: Seq[Filter[Query, AdsCandidate]],
- override val postFilterFeatureHydration: Seq[
- BaseCandidateFeatureHydrator[Query, AdsCandidate, _]
- ],
- override val decorator: Option[CandidateDecorator[Query, AdsCandidate]],
- override val alerts: Seq[Alert],
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- urtRequest: Option[Boolean],
- getOrganicItemIds: GetOrganicItemIds,
- countNumOrganicItems: CountNumOrganicItems[Query],
-) extends DependentCandidatePipelineConfig[
- Query,
- ads.AdRequestParams,
- ads.AdImpression,
- AdsCandidate
- ] {
-
- override def queryTransformer: DependentCandidatePipelineQueryTransformer[
- Query,
- ads.AdRequestParams
- ] = AdsDependentCandidatePipelineQueryTransformer(
- adsDisplayLocationBuilder = adsDisplayLocationBuilder,
- getOrganicItemIds = getOrganicItemIds,
- countNumOrganicItems = countNumOrganicItems,
- urtRequest = urtRequest
- )
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- ads.AdImpression,
- AdsCandidate
- ] = AdsCandidatePipelineResultsTransformer
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 6cdf573c8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.thriftscala.AdImpression
-import com.twitter.adserver.thriftscala.AdRequestParams
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad.AdsCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsDependentCandidatePipelineConfigBuilder @Inject() () {
-
- /**
- * Build a AdsDependentCandidatePipelineConfig
- */
- def build[Query <: PipelineQuery with AdsQuery](
- adsCandidateSource: CandidateSource[AdRequestParams, AdImpression],
- identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("Ads"),
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- getOrganicItemIds: GetOrganicItemIds = EmptyOrganicItemIds,
- countNumOrganicItems: CountNumOrganicItems[Query] = CountAllCandidates,
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- gates: Seq[BaseGate[Query]] = Seq.empty,
- filters: Seq[Filter[Query, AdsCandidate]] = Seq.empty,
- postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, AdsCandidate, _]] =
- Seq.empty,
- decorator: Option[CandidateDecorator[Query, AdsCandidate]] =
- Some(UrtItemCandidateDecorator(AdsCandidateUrtItemBuilder())),
- alerts: Seq[Alert] = Seq.empty,
- urtRequest: Option[Boolean] = None,
- ): AdsDependentCandidatePipelineConfig[Query] = new AdsDependentCandidatePipelineConfig[Query](
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- gates = gates,
- candidateSource = adsCandidateSource,
- filters = filters,
- postFilterFeatureHydration = postFilterFeatureHydration,
- decorator = decorator,
- alerts = alerts,
- adsDisplayLocationBuilder = adsDisplayLocationBuilder,
- getOrganicItemIds = getOrganicItemIds,
- countNumOrganicItems = countNumOrganicItems,
- urtRequest = urtRequest)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala
deleted file mode 100644
index 2dc5a1628..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.component_library.pipeline.candidate.ads.AdsCandidatePipelineQueryTransformer.buildAdRequestParams
-import com.twitter.product_mixer.core.functional_component.transformer.DependentCandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Transform a PipelineQuery with AdsQuery into an AdsRequestParams
- *
- * @param adsDisplayLocationBuilder Builder that determines the display location for the ads
- * @param countNumOrganicItems Count organic items from the response
- */
-case class AdsDependentCandidatePipelineQueryTransformer[Query <: PipelineQuery with AdsQuery](
- adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query],
- getOrganicItemIds: GetOrganicItemIds,
- countNumOrganicItems: CountNumOrganicItems[Query],
- urtRequest: Option[Boolean],
-) extends DependentCandidatePipelineQueryTransformer[Query, ads.AdRequestParams] {
-
- override def transform(
- query: Query,
- previousCandidates: Seq[CandidateWithDetails]
- ): ads.AdRequestParams = buildAdRequestParams(
- query = query,
- adsDisplayLocation = adsDisplayLocationBuilder(query),
- organicItemIds = getOrganicItemIds.apply(previousCandidates),
- numOrganicItems = Some(countNumOrganicItems.apply(query, previousCandidates)),
- urtRequest = urtRequest
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala
deleted file mode 100644
index e10ce6a12..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.adserver.{thriftscala => ads}
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait AdsDisplayLocationBuilder[-Query <: PipelineQuery with AdsQuery] {
-
- def apply(query: Query): ads.DisplayLocation
-}
-
-case class StaticAdsDisplayLocationBuilder(displayLocation: ads.DisplayLocation)
- extends AdsDisplayLocationBuilder[PipelineQuery with AdsQuery] {
-
- def apply(query: PipelineQuery with AdsQuery): ads.DisplayLocation = displayLocation
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD
deleted file mode 100644
index c459215e5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala
deleted file mode 100644
index c42abfa7b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Derive an estimate of the number of organic items from the query. If you need a more precise number,
- * consider switching to [[AdsDependentCandidatePipelineConfig]]
- */
-trait EstimateNumOrganicItems[Query <: PipelineQuery with AdsQuery] {
-
- def apply(query: Query): Short
-}
-
-/**
- * Compute the number of organic items from the query and set of previous candidates.
- *
- * @note the key difference between [[CountNumOrganicItems]] and [[EstimateNumOrganicItems]] is
- * that for [[EstimateNumOrganicItems]] we don't have any candidates returned yet, so we can
- * only guess as to the number of organic items in the result set. In contrast,
- * [[CountNumOrganicItems]] is used on dependant candidate pipelines where we can scan over
- * the candidate pipelines result set to count the number of organic items.
- */
-trait CountNumOrganicItems[-Query <: PipelineQuery with AdsQuery] {
-
- def apply(query: Query, previousCandidates: Seq[CandidateWithDetails]): Short
-}
-
-/**
- * Treat all previously retrieved candidates as organic
- */
-case object CountAllCandidates extends CountNumOrganicItems[PipelineQuery with AdsQuery] {
-
- def apply(
- query: PipelineQuery with AdsQuery,
- previousCandidates: Seq[CandidateWithDetails]
- ): Short =
- previousCandidates.length.toShort
-}
-
-/**
- * Only count candidates from a specific subset of pipelines as organic
- */
-case class CountCandidatesFromPipelines(pipelines: CandidateScope)
- extends CountNumOrganicItems[PipelineQuery with AdsQuery] {
-
- def apply(
- query: PipelineQuery with AdsQuery,
- previousCandidates: Seq[CandidateWithDetails]
- ): Short =
- previousCandidates.count(pipelines.contains).toShort
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala
deleted file mode 100644
index 9682ad5c9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-/**
- * Get organic item candidates from the set of previous candidates
- */
-trait GetOrganicItemIds {
-
- def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]]
-}
-
-/**
- * Get organic items from specified pipelines
- */
-case class PipelineScopedOrganicItemIds(pipelines: CandidateScope) extends GetOrganicItemIds {
-
- def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]] =
- Some(previousCandidates.filter(pipelines.contains).map(_.candidateIdLong))
-}
-
-/**
- * Get an empty list of organic item candidates
- */
-case object EmptyOrganicItemIds extends GetOrganicItemIds {
-
- def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]] = None
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala
deleted file mode 100644
index ef323aa6a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-case class PromotedTweetsOnlyFilter[Query <: PipelineQuery](
- underlyingFilter: Filter[Query, AdsTweetCandidate])
- extends Filter[Query, AdsCandidate] {
-
- override val identifier: FilterIdentifier =
- FilterIdentifier(s"PromotedTweets${underlyingFilter.identifier.name}")
-
- override def apply(
- query: Query,
- candidatesWithFeatures: Seq[CandidateWithFeatures[AdsCandidate]]
- ): Stitch[FilterResult[AdsCandidate]] = {
-
- val adsTweetCandidates: Seq[CandidateWithFeatures[AdsTweetCandidate]] =
- candidatesWithFeatures.flatMap {
- case tweetCandidateWithFeatures @ CandidateWithFeatures(_: AdsTweetCandidate, _) =>
- Some(tweetCandidateWithFeatures.asInstanceOf[CandidateWithFeatures[AdsTweetCandidate]])
- case _ => None
- }
-
- underlyingFilter
- .apply(query, adsTweetCandidates)
- .map { filterResult =>
- val removedSet = filterResult.removed.toSet[AdsCandidate]
- val (removed, kept) = candidatesWithFeatures.map(_.candidate).partition(removedSet.contains)
- FilterResult(kept, removed)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala
deleted file mode 100644
index 4064a69cc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.ads
-
-import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.filter.FilterResult
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object ValidAdImpressionIdFilter extends Filter[PipelineQuery, AdsCandidate] {
- override val identifier: FilterIdentifier = FilterIdentifier("ValidAdImpressionId")
-
- override def apply(
- query: PipelineQuery,
- candidatesWithFeatures: Seq[CandidateWithFeatures[AdsCandidate]]
- ): Stitch[FilterResult[AdsCandidate]] = {
- val (kept, removed) = candidatesWithFeatures
- .map(_.candidate)
- .partition(candidate => candidate.adImpression.impressionString.exists(_.nonEmpty))
-
- Stitch.value(FilterResult(kept, removed))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel
deleted file mode 100644
index ef2575873..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala
deleted file mode 100644
index 88d522175..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline
-
-import com.twitter.onboarding.task.service.thriftscala.GetInjectionsRequest
-import com.twitter.onboarding.task.service.{thriftscala => servicethrift}
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.UrtMultipleModulesDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptModuleGrouping
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptUrtModuleBuilder
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipCandidateFeatureTransformer
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipQueryTransformer
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.PromptResultsTransformer
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-/**
- * A candidate pipeline for Flexible Injection Pipeline Candidates.
- * Fetches prompts from FLIP (inside onboarding-task-service).
- */
-class FlipPromptCandidatePipelineConfig[Query <: PipelineQuery with HasFlipInjectionParams](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- promptCandidateSource: PromptCandidateSource)
- extends CandidatePipelineConfig[
- Query,
- servicethrift.GetInjectionsRequest,
- IntermediatePrompt,
- BasePromptCandidate[Any]
- ] {
-
- override val candidateSource: CandidateSource[GetInjectionsRequest, IntermediatePrompt] =
- promptCandidateSource
-
- override val queryTransformer: CandidatePipelineQueryTransformer[Query, GetInjectionsRequest] =
- FlipQueryTransformer
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- IntermediatePrompt,
- BasePromptCandidate[Any]
- ] = PromptResultsTransformer
-
- override val decorator: Option[
- CandidateDecorator[Query, BasePromptCandidate[Any]]
- ] = Some(
- UrtMultipleModulesDecorator(
- urtItemCandidateDecorator = UrtItemCandidateDecorator(FlipPromptCandidateUrtItemBuilder()),
- moduleBuilder = FlipPromptUrtModuleBuilder(),
- groupByKey = FlipPromptModuleGrouping
- ))
-
- override val featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[IntermediatePrompt]
- ] = Seq(FlipCandidateFeatureTransformer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 199eb73f2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline
-
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FlipPromptCandidatePipelineConfigBuilder @Inject() (
- promptCandidateSource: PromptCandidateSource) {
-
- /**
- * Build a FlipPromptCandidatePipelineConfig
- *
- * @note If injected classes are needed to populate parameters in this method, consider creating a
- * ProductFlipPromptCandidatePipelineConfigBuilder with a single `def build()` method.
- * That product-specific builder class can then inject everything it needs (including this
- * class), and delegate to this class's build() method within its own build() method.
- */
- def build[Query <: PipelineQuery with HasFlipInjectionParams](
- identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("FlipPrompt"),
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- ): FlipPromptCandidatePipelineConfig[Query] = {
- new FlipPromptCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- promptCandidateSource = promptCandidateSource)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala
deleted file mode 100644
index 537c91639..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline
-
-import com.twitter.onboarding.task.service.thriftscala.GetInjectionsRequest
-import com.twitter.onboarding.task.service.{thriftscala => servicethrift}
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.UrtMultipleModulesDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptModuleGrouping
-import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptUrtModuleBuilder
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipCandidateFeatureTransformer
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipQueryTransformer
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.PromptResultsTransformer
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-/**
- * A dependent candidate pipeline for Flexible Injection Pipeline Candidates.
- * Fetches prompts from FLIP (inside onboarding-task-service).
- */
-class FlipPromptDependentCandidatePipelineConfig[
- Query <: PipelineQuery with HasFlipInjectionParams
-](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- promptCandidateSource: PromptCandidateSource)
- extends DependentCandidatePipelineConfig[
- Query,
- servicethrift.GetInjectionsRequest,
- IntermediatePrompt,
- BasePromptCandidate[Any]
- ] {
-
- override val candidateSource: CandidateSource[GetInjectionsRequest, IntermediatePrompt] =
- promptCandidateSource
-
- override val queryTransformer: CandidatePipelineQueryTransformer[Query, GetInjectionsRequest] =
- FlipQueryTransformer
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- IntermediatePrompt,
- BasePromptCandidate[Any]
- ] = PromptResultsTransformer
-
- override val decorator: Option[
- CandidateDecorator[Query, BasePromptCandidate[Any]]
- ] = Some(
- UrtMultipleModulesDecorator(
- urtItemCandidateDecorator = UrtItemCandidateDecorator(FlipPromptCandidateUrtItemBuilder()),
- moduleBuilder = FlipPromptUrtModuleBuilder(),
- groupByKey = FlipPromptModuleGrouping
- ))
-
- override val featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[IntermediatePrompt]
- ] = Seq(FlipCandidateFeatureTransformer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 87c5e080c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline
-
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource
-import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FlipPromptDependentCandidatePipelineConfigBuilder @Inject() (
- promptCandidateSource: PromptCandidateSource) {
-
- /**
- * Build a FlipPromptDependentCandidatePipelineConfig
- *
- * @note If injected classes are needed to populate parameters in this method, consider creating a
- * ProductFlipPromptDependentCandidatePipelineConfigBuilder with a single `def build()` method.
- * That product-specific builder class can then inject everything it needs (including this
- * class), and delegate to this class's build() method within its own build() method.
- */
- def build[Query <: PipelineQuery with HasFlipInjectionParams](
- identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("FlipPrompt"),
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- ): FlipPromptDependentCandidatePipelineConfig[Query] = {
- new FlipPromptDependentCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- promptCandidateSource = promptCandidateSource)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD
deleted file mode 100644
index 5b4460cec..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "onboarding/service/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala
deleted file mode 100644
index 78d0fa58a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer
-
-import com.twitter.onboarding.injections.{thriftscala => onboardingthrift}
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-case object FlipPromptCarouselTileFeature
- extends Feature[PromptCarouselTileCandidate, Option[onboardingthrift.Tile]]
-
-case object FlipPromptInjectionsFeature
- extends Feature[BasePromptCandidate[String], onboardingthrift.Injection]
-
-case object FlipPromptOffsetInModuleFeature
- extends Feature[PromptCarouselTileCandidate, Option[Int]]
-
-object FlipCandidateFeatureTransformer extends CandidateFeatureTransformer[IntermediatePrompt] {
-
- override val identifier: TransformerIdentifier = TransformerIdentifier("FlipCandidateFeature")
-
- override val features: Set[Feature[_, _]] =
- Set(FlipPromptInjectionsFeature, FlipPromptOffsetInModuleFeature, FlipPromptCarouselTileFeature)
-
- /** Hydrates a [[FeatureMap]] for a given [[Inputs]] */
- override def transform(input: IntermediatePrompt): FeatureMap = {
- FeatureMapBuilder()
- .add(FlipPromptInjectionsFeature, input.injection)
- .add(FlipPromptOffsetInModuleFeature, input.offsetInModule)
- .add(FlipPromptCarouselTileFeature, input.carouselTile)
- .build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala
deleted file mode 100644
index bcb84f375..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer
-
-import com.twitter.onboarding.task.service.{thriftscala => flip}
-
-trait HasFlipInjectionParams {
- def displayLocation: flip.DisplayLocation
- def rankingDisablerWithLatestControlsAvailable: Option[Boolean]
- def isEmptyState: Option[Boolean]
- def isFirstRequestAfterSignup: Option[Boolean]
- def isEndOfTimeline: Option[Boolean]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala
deleted file mode 100644
index e80cfe2aa..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer
-
-import com.twitter.onboarding.task.service.thriftscala.PromptType
-import com.twitter.onboarding.task.service.{thriftscala => flip}
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object FlipQueryTransformer
- extends CandidatePipelineQueryTransformer[
- PipelineQuery with HasFlipInjectionParams,
- flip.GetInjectionsRequest
- ] {
-
- val SUPPORTED_PROMPT_TYPES: Set[PromptType] = Set(
- PromptType.InlinePrompt,
- PromptType.FullCover,
- PromptType.HalfCover,
- PromptType.TileCarousel,
- PromptType.RelevancePrompt)
-
- override def transform(
- query: PipelineQuery with HasFlipInjectionParams
- ): flip.GetInjectionsRequest = {
- val clientContext = flip.ClientContext(
- userId = query.clientContext.userId,
- guestId = query.clientContext.guestId,
- clientApplicationId = query.clientContext.appId,
- deviceId = query.clientContext.deviceId,
- countryCode = query.clientContext.countryCode,
- languageCode = query.clientContext.languageCode,
- userAgent = query.clientContext.userAgent,
- guestIdMarketing = query.clientContext.guestIdMarketing,
- guestIdAds = query.clientContext.guestIdAds,
- isInternalOrTwoffice = query.clientContext.isTwoffice,
- ipAddress = query.clientContext.ipAddress
- )
- val displayContext: flip.DisplayContext =
- flip.DisplayContext(
- displayLocation = query.displayLocation,
- timelineId = query.clientContext.userId
- )
-
- val requestTargetingContext: flip.RequestTargetingContext =
- flip.RequestTargetingContext(
- rankingDisablerWithLatestControlsAvaliable =
- query.rankingDisablerWithLatestControlsAvailable,
- reactivePromptContext = None,
- isEmptyState = query.isEmptyState,
- isFirstRequestAfterSignup = query.isFirstRequestAfterSignup,
- isEndOfTimeline = query.isEndOfTimeline
- )
-
- flip.GetInjectionsRequest(
- clientContext = clientContext,
- displayContext = displayContext,
- requestTargetingContext = Some(requestTargetingContext),
- userRoles = query.clientContext.userRoles,
- timelineContext = None,
- supportedPromptTypes = Some(SUPPORTED_PROMPT_TYPES)
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala
deleted file mode 100644
index d195aa0f8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer
-
-import com.twitter.onboarding.injections.{thriftscala => flipinjection}
-import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt
-import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate
-import com.twitter.product_mixer.component_library.model.candidate.FullCoverPromptCandidate
-import com.twitter.product_mixer.component_library.model.candidate.HalfCoverPromptCandidate
-import com.twitter.product_mixer.component_library.model.candidate.InlinePromptCandidate
-import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate
-import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-
-object PromptResultsTransformer
- extends CandidatePipelineResultsTransformer[
- IntermediatePrompt,
- BasePromptCandidate[Any]
- ] {
-
- /**
- * Transforms a Flip Injection to a Product Mixer domain object deriving from BasePromptCandidate.
- * Supported injection types have to match those declared in com.twitter.product_mixer.component_library.transformer.flexible_injection_pipeline.FlipQueryTransformer#supportedPromptFormats
- */
- override def transform(input: IntermediatePrompt): BasePromptCandidate[Any] =
- input.injection match {
- case inlinePrompt: flipinjection.Injection.InlinePrompt =>
- InlinePromptCandidate(id = inlinePrompt.inlinePrompt.injectionIdentifier
- .getOrElse(throw new MissingInjectionId(input.injection)))
- case _: flipinjection.Injection.FullCover =>
- FullCoverPromptCandidate(id = "0")
- case _: flipinjection.Injection.HalfCover =>
- HalfCoverPromptCandidate(id = "0")
- case _: flipinjection.Injection.TilesCarousel =>
- PromptCarouselTileCandidate(id =
- input.offsetInModule.getOrElse(throw FlipPromptOffsetInModuleMissing))
- case relevancePrompt: flipinjection.Injection.RelevancePrompt =>
- RelevancePromptCandidate(
- id = relevancePrompt.relevancePrompt.injectionIdentifier,
- position = relevancePrompt.relevancePrompt.requestedPosition.map(_.toInt))
- case injection => throw new UnsupportedInjectionType(injection)
- }
-}
-
-class MissingInjectionId(injection: flipinjection.Injection)
- extends IllegalArgumentException(
- s"Injection identifier is missing ${TransportMarshaller.getSimpleName(injection.getClass)}")
-
-class UnsupportedInjectionType(injection: flipinjection.Injection)
- extends UnsupportedOperationException(
- s"Unsupported FLIP injection Type : ${TransportMarshaller.getSimpleName(injection.getClass)}")
-
-object FlipPromptOffsetInModuleMissing
- extends NoSuchElementException(
- "FlipPromptOffsetInModuleFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel
deleted file mode 100644
index 0146a3493..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "servo/repo/src/main/scala",
- "src/thrift/com/twitter/hermit/internal:hermit-internal-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala
deleted file mode 100644
index 8763389af..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.WhoToFollowModuleFooterFeature
-import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.WhoToFollowModuleHeaderFeature
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemInModuleDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ClientEventInfoBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.StaticUrlBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.promoted.FeaturePromotedMetadataBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.social_context.WhoToFollowSocialContextBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.StrStatic
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleFooterBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleHeaderBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.TimelineModuleBuilder
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object WhoToFollowArmCandidateDecorator {
- val ClientEventComponent = "suggest_who_to_follow"
- val EntryNamespaceString = "who-to-follow"
-}
-
-case class WhoToFollowArmCandidateDecorator[-Query <: PipelineQuery](
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, UserCandidate]
- ]) extends CandidateDecorator[Query, UserCandidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[UserCandidate]]
- ): Stitch[Seq[Decoration]] = {
- val clientEventDetailsBuilder = WhoToFollowClientEventDetailsBuilder(TrackingTokenFeature)
- val clientEventInfoBuilder = ClientEventInfoBuilder[Query, UserCandidate](
- WhoToFollowArmCandidateDecorator.ClientEventComponent,
- Some(clientEventDetailsBuilder))
- val promotedMetadataBuilder = FeaturePromotedMetadataBuilder(AdImpressionFeature)
- val socialContextBuilder =
- WhoToFollowSocialContextBuilder(SocialTextFeature, HermitContextTypeFeature)
- val userItemBuilder = UserCandidateUrtItemBuilder(
- clientEventInfoBuilder = clientEventInfoBuilder,
- promotedMetadataBuilder = Some(promotedMetadataBuilder),
- socialContextBuilder = Some(socialContextBuilder))
- val userItemDecorator = UrtItemCandidateDecorator(userItemBuilder)
-
- val whoToFollowModuleBuilder = {
- val whoToFollowHeaderOpt = query.features.map(_.get(WhoToFollowModuleHeaderFeature))
- val whoToFollowFooterOpt = query.features.flatMap(_.get(WhoToFollowModuleFooterFeature))
- val whoToFollowModuleHeaderBuilder = whoToFollowHeaderOpt.flatMap(_.title).map { title =>
- ModuleHeaderBuilder(textBuilder = StrStatic(title), isSticky = Some(true))
- }
- val whoToFollowModuleFooterBuilder = whoToFollowFooterOpt.flatMap(_.action).map { action =>
- ModuleFooterBuilder(
- textBuilder = StrStatic(action.title),
- urlBuilder = Some(StaticUrlBuilder(action.actionUrl, DeepLink)))
- }
-
- TimelineModuleBuilder(
- entryNamespace = EntryNamespace(WhoToFollowArmCandidateDecorator.EntryNamespaceString),
- clientEventInfoBuilder = clientEventInfoBuilder,
- displayTypeBuilder = moduleDisplayTypeBuilder,
- headerBuilder = whoToFollowModuleHeaderBuilder,
- footerBuilder = whoToFollowModuleFooterBuilder,
- feedbackActionInfoBuilder = feedbackActionInfoBuilder,
- )
- }
-
- UrtItemInModuleDecorator(
- userItemDecorator,
- whoToFollowModuleBuilder
- ).apply(query, candidates)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala
deleted file mode 100644
index d72241fd2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-
-object WhoToFollowArmCandidatePipelineConfig {
- val MinCandidatesSize = 3
- val MaxCandidatesSize = 20
-
- val identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("WhoToFollowArm")
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala
deleted file mode 100644
index bfcf877ce..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.account_recommendations_mixer.{thriftscala => t}
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.marshaller.request.ClientContextMarshaller
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest
-import com.twitter.timelines.configapi.Param
-
-object WhoToFollowArmCandidatePipelineQueryTransformer {
- val HomeDisplayLocation = "timeline"
- val HomeReverseChronDisplayLocation = "timeline_reverse_chron"
- val ProfileDisplayLocation = "profile_timeline"
-}
-
-case class WhoToFollowArmCandidatePipelineQueryTransformer[-Query <: PipelineQuery](
- displayLocationParam: Param[String],
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]],
- profileUserIdFeature: Option[Feature[PipelineQuery, Long]])
- extends CandidatePipelineQueryTransformer[Query, t.AccountRecommendationsMixerRequest] {
-
- override def transform(input: Query): t.AccountRecommendationsMixerRequest = {
- input.params(displayLocationParam) match {
- case WhoToFollowArmCandidatePipelineQueryTransformer.HomeReverseChronDisplayLocation =>
- t.AccountRecommendationsMixerRequest(
- clientContext = ClientContextMarshaller(input.clientContext),
- product = t.Product.HomeReverseChronWhoToFollow,
- productContext = Some(
- t.ProductContext.HomeReverseChronWhoToFollowProductContext(
- t.HomeReverseChronWhoToFollowProductContext(
- wtfReactiveContext = Some(getWhoToFollowReactiveContext(input))
- )))
- )
- case WhoToFollowArmCandidatePipelineQueryTransformer.HomeDisplayLocation =>
- t.AccountRecommendationsMixerRequest(
- clientContext = ClientContextMarshaller(input.clientContext),
- product = t.Product.HomeWhoToFollow,
- productContext = Some(
- t.ProductContext.HomeWhoToFollowProductContext(
- t.HomeWhoToFollowProductContext(
- wtfReactiveContext = Some(getWhoToFollowReactiveContext(input))
- )))
- )
- case WhoToFollowArmCandidatePipelineQueryTransformer.ProfileDisplayLocation =>
- t.AccountRecommendationsMixerRequest(
- clientContext = ClientContextMarshaller(input.clientContext),
- product = t.Product.ProfileWhoToFollow,
- productContext = Some(
- t.ProductContext.ProfileWhoToFollowProductContext(t.ProfileWhoToFollowProductContext(
- wtfReactiveContext = Some(getWhoToFollowReactiveContext(input)),
- profileUserId = profileUserIdFeature
- .flatMap(feature => input.features.map(_.get(feature)))
- .getOrElse(throw PipelineFailure(BadRequest, "profileUserId not provided")),
- )))
- )
- case displayLocation =>
- throw PipelineFailure(BadRequest, s"display location $displayLocation not supported")
- }
- }
-
- private def getWhoToFollowReactiveContext(
- input: Query
- ): t.WhoToFollowReactiveContext = {
- t.WhoToFollowReactiveContext(
- excludedUserIds = excludedUserIdsFeature.flatMap(feature =>
- input.features
- .map(_.get(feature))),
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala
deleted file mode 100644
index f1e7b3ca7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.account_recommendations_mixer.{thriftscala => t}
-import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.AccountRecommendationsMixerCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-class WhoToFollowArmDependentCandidatePipelineConfig[Query <: PipelineQuery](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- override val alerts: Seq[Alert],
- override val gates: Seq[BaseGate[Query]],
- accountRecommendationsMixerCandidateSource: AccountRecommendationsMixerCandidateSource,
- override val filters: Seq[Filter[Query, UserCandidate]],
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate]
- ],
- displayLocationParam: Param[String],
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]],
- profileUserIdFeature: Option[Feature[PipelineQuery, Long]])
- extends DependentCandidatePipelineConfig[
- Query,
- t.AccountRecommendationsMixerRequest,
- t.RecommendedUser,
- UserCandidate
- ] {
-
- override val candidateSource: BaseCandidateSource[
- t.AccountRecommendationsMixerRequest,
- t.RecommendedUser
- ] =
- accountRecommendationsMixerCandidateSource
-
- override val queryTransformer: CandidatePipelineQueryTransformer[
- PipelineQuery,
- t.AccountRecommendationsMixerRequest
- ] = WhoToFollowArmCandidatePipelineQueryTransformer(
- displayLocationParam = displayLocationParam,
- excludedUserIdsFeature = excludedUserIdsFeature,
- profileUserIdFeature = profileUserIdFeature
- )
-
- override val featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[t.RecommendedUser]
- ] = Seq(WhoToFollowArmResponseFeatureTransformer)
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- t.RecommendedUser,
- UserCandidate
- ] = { user => UserCandidate(user.userId) }
-
- override val decorator: Option[CandidateDecorator[Query, UserCandidate]] =
- Some(
- WhoToFollowArmCandidateDecorator(
- moduleDisplayTypeBuilder,
- feedbackActionInfoBuilder
- ))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 91eb9b1bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.AccountRecommendationsMixerCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class WhoToFollowArmDependentCandidatePipelineConfigBuilder @Inject() (
- accountRecommendationsMixerCandidateSource: AccountRecommendationsMixerCandidateSource) {
-
- /**
- * Build a WhoToFollowArmDependentCandidatePipelineConfig
- *
- *
- * To create a regular CandidatePipelineConfig instead see [[WhoToFollowArmCandidatePipelineConfigBuilder]].
- *
- * @note If injected classes are needed to populate parameters in this method, consider creating a
- * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That
- * product-specific builder class can then inject everything it needs (including this class),
- * and delegate to this class's build() method within its own build() method.
- */
- def build[Query <: PipelineQuery](
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- identifier: CandidatePipelineIdentifier = WhoToFollowArmCandidatePipelineConfig.identifier,
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- alerts: Seq[Alert] = Seq.empty,
- gates: Seq[BaseGate[Query]] = Seq.empty,
- filters: Seq[Filter[Query, UserCandidate]] = Seq.empty,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[
- PipelineQuery,
- UserCandidate
- ]] = None,
- displayLocationParam: Param[String] =
- StaticParam(WhoToFollowArmCandidatePipelineQueryTransformer.HomeDisplayLocation),
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]],
- profileUserIdFeature: Option[Feature[PipelineQuery, Long]]
- ): WhoToFollowArmDependentCandidatePipelineConfig[Query] =
- new WhoToFollowArmDependentCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- alerts = alerts,
- gates = gates,
- accountRecommendationsMixerCandidateSource = accountRecommendationsMixerCandidateSource,
- filters = filters,
- moduleDisplayTypeBuilder = moduleDisplayTypeBuilder,
- feedbackActionInfoBuilder = feedbackActionInfoBuilder,
- displayLocationParam = displayLocationParam,
- excludedUserIdsFeature = excludedUserIdsFeature,
- profileUserIdFeature = profileUserIdFeature
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala
deleted file mode 100644
index 4ee90a4bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.hermit.{thriftscala => h}
-import com.twitter.account_recommendations_mixer.{thriftscala => t}
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-object ContextTypeFeature extends Feature[UserCandidate, Option[t.ContextType]]
-
-object WhoToFollowArmResponseFeatureTransformer
- extends CandidateFeatureTransformer[t.RecommendedUser] {
-
- override val identifier: TransformerIdentifier = TransformerIdentifier("WhoToFollowArmResponse")
-
- override val features: Set[Feature[_, _]] =
- Set(
- AdImpressionFeature,
- ContextTypeFeature,
- HermitContextTypeFeature,
- SocialTextFeature,
- TrackingTokenFeature,
- ScoreFeature)
-
- override def transform(input: t.RecommendedUser): FeatureMap = FeatureMapBuilder()
- .add(AdImpressionFeature, input.adImpression)
- .add(ContextTypeFeature, input.contextType)
- .add(
- HermitContextTypeFeature,
- input.contextType.map(contextType => h.ContextType(contextType.value)))
- .add(SocialTextFeature, input.socialText)
- .add(TrackingTokenFeature, input.trackingToken)
- .add(ScoreFeature, input.mlPredictionScore)
- .build()
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala
deleted file mode 100644
index 763c860d0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.WhoToFollowModuleHeaderFeature
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.WhoToFollowModuleShowMoreFeature
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.UrtItemInModuleDecorator
-import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ClientEventInfoBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.StaticUrlBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.promoted.FeaturePromotedMetadataBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.social_context.WhoToFollowSocialContextBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.StrStatic
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleDynamicShowMoreBehaviorRevealByCountBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleFooterBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleHeaderBuilder
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.TimelineModuleBuilder
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-object WhoToFollowCandidateDecorator {
- val ClientEventComponent = "suggest_who_to_follow"
- val EntryNamespaceString = "who-to-follow"
-}
-
-case class WhoToFollowCandidateDecorator[-Query <: PipelineQuery](
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[Query, UserCandidate]
- ]) extends CandidateDecorator[Query, UserCandidate] {
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[UserCandidate]]
- ): Stitch[Seq[Decoration]] = {
- val clientEventDetailsBuilder = WhoToFollowClientEventDetailsBuilder(TrackingTokenFeature)
- val clientEventInfoBuilder = ClientEventInfoBuilder[Query, UserCandidate](
- WhoToFollowCandidateDecorator.ClientEventComponent,
- Some(clientEventDetailsBuilder))
- val promotedMetadataBuilder = FeaturePromotedMetadataBuilder(AdImpressionFeature)
- val socialContextBuilder =
- WhoToFollowSocialContextBuilder(SocialTextFeature, HermitContextTypeFeature)
- val userItemBuilder = UserCandidateUrtItemBuilder(
- clientEventInfoBuilder = clientEventInfoBuilder,
- promotedMetadataBuilder = Some(promotedMetadataBuilder),
- socialContextBuilder = Some(socialContextBuilder))
- val userItemDecorator = UrtItemCandidateDecorator(userItemBuilder)
-
- val whoToFollowModuleBuilder = {
- val whoToFollowHeaderOpt = query.features.map(_.get(WhoToFollowModuleHeaderFeature))
- val whoToFollowModuleHeaderBuilder = whoToFollowHeaderOpt.flatMap(_.title).map { title =>
- ModuleHeaderBuilder(textBuilder = StrStatic(title.text), isSticky = Some(true))
- }
- val whoToFollowModuleFooterBuilder = whoToFollowHeaderOpt.flatMap(_.action).map { action =>
- ModuleFooterBuilder(
- textBuilder = StrStatic(action.title),
- urlBuilder = Some(StaticUrlBuilder(action.actionUrl, DeepLink)))
- }
- val showMoreBehaviorBuilder =
- query.features.flatMap(_.get(WhoToFollowModuleShowMoreFeature)).map { showMore =>
- ModuleDynamicShowMoreBehaviorRevealByCountBuilder(
- showMore.initialToShow,
- showMore.extraToShow)
- }
-
- TimelineModuleBuilder(
- entryNamespace = EntryNamespace(WhoToFollowCandidateDecorator.EntryNamespaceString),
- clientEventInfoBuilder = clientEventInfoBuilder,
- displayTypeBuilder = moduleDisplayTypeBuilder,
- headerBuilder = whoToFollowModuleHeaderBuilder,
- footerBuilder = whoToFollowModuleFooterBuilder,
- feedbackActionInfoBuilder = feedbackActionInfoBuilder,
- showMoreBehaviorBuilder = showMoreBehaviorBuilder
- )
- }
-
- UrtItemInModuleDecorator(
- userItemDecorator,
- whoToFollowModuleBuilder
- ).apply(query, candidates)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala
deleted file mode 100644
index 55888e38d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.peoplediscovery.api.{thriftscala => t}
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-object WhoToFollowCandidatePipelineConfig {
- val MinCandidatesSize = 3
- val MaxCandidatesSize = 20
-
- val identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("WhoToFollow")
-}
-
-class WhoToFollowCandidatePipelineConfig[Query <: PipelineQuery](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- override val alerts: Seq[Alert],
- override val gates: Seq[Gate[Query]],
- whoToFollowCandidateSource: PeopleDiscoveryCandidateSource,
- override val filters: Seq[Filter[Query, UserCandidate]],
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate]
- ],
- displayLocationParam: Param[String],
- supportedLayoutsParam: Param[Seq[String]],
- layoutVersionParam: Param[Int],
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]],
-) extends CandidatePipelineConfig[
- Query,
- t.GetModuleRequest,
- t.RecommendedUser,
- UserCandidate
- ] {
-
- override val candidateSource: BaseCandidateSource[t.GetModuleRequest, t.RecommendedUser] =
- whoToFollowCandidateSource
-
- override val queryTransformer: CandidatePipelineQueryTransformer[
- PipelineQuery,
- t.GetModuleRequest
- ] = WhoToFollowCandidatePipelineQueryTransformer(
- displayLocationParam,
- supportedLayoutsParam,
- layoutVersionParam,
- excludedUserIdsFeature)
-
- override val featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[t.RecommendedUser]
- ] = Seq(WhoToFollowResponseFeatureTransformer)
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- t.RecommendedUser,
- UserCandidate
- ] = { user => UserCandidate(user.userId) }
-
- override val decorator: Option[CandidateDecorator[Query, UserCandidate]] =
- Some(WhoToFollowCandidateDecorator(moduleDisplayTypeBuilder, feedbackActionInfoBuilder))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 5c50bbb85..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class WhoToFollowCandidatePipelineConfigBuilder @Inject() (
- whoToFollowCandidateSource: PeopleDiscoveryCandidateSource) {
-
- /**
- * Build a WhoToFollowCandidatePipelineConfig
- *
- * To create a DependentCandidatePipelineConfig instead see [[WhoToFollowDependentCandidatePipelineConfigBuilder]].
- *
- * @note If injected classes are needed to populate parameters in this method, consider creating a
- * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That
- * product-specific builder class can then inject everything it needs (including this class),
- * and delegate to this class's build() method within its own build() method.
- */
- def build[Query <: PipelineQuery](
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- identifier: CandidatePipelineIdentifier = WhoToFollowCandidatePipelineConfig.identifier,
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- alerts: Seq[Alert] = Seq.empty,
- gates: Seq[Gate[Query]] = Seq.empty,
- filters: Seq[Filter[Query, UserCandidate]] = Seq.empty,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[
- PipelineQuery,
- UserCandidate
- ]] = None,
- displayLocationParam: Param[String] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.DisplayLocation),
- supportedLayoutsParam: Param[Seq[String]] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.SupportedLayouts),
- layoutVersionParam: Param[Int] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.LayoutVersion),
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]] = None,
- ): WhoToFollowCandidatePipelineConfig[Query] =
- new WhoToFollowCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- alerts = alerts,
- gates = gates,
- moduleDisplayTypeBuilder = moduleDisplayTypeBuilder,
- whoToFollowCandidateSource = whoToFollowCandidateSource,
- filters = filters,
- feedbackActionInfoBuilder = feedbackActionInfoBuilder,
- displayLocationParam = displayLocationParam,
- supportedLayoutsParam = supportedLayoutsParam,
- layoutVersionParam = layoutVersionParam,
- excludedUserIdsFeature = excludedUserIdsFeature
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala
deleted file mode 100644
index f4ba0558f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.peoplediscovery.api.thriftscala.ClientContext
-import com.twitter.peoplediscovery.api.thriftscala.GetModuleRequest
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-object WhoToFollowCandidatePipelineQueryTransformer {
- val DisplayLocation = "timeline"
- val SupportedLayouts = Seq("user-bio-list")
- val LayoutVersion = 2
-}
-
-case class WhoToFollowCandidatePipelineQueryTransformer[-Query <: PipelineQuery](
- displayLocationParam: Param[String],
- supportedLayoutsParam: Param[Seq[String]],
- layoutVersionParam: Param[Int],
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]],
-) extends CandidatePipelineQueryTransformer[Query, GetModuleRequest] {
-
- override def transform(input: Query): GetModuleRequest =
- GetModuleRequest(
- clientContext = ClientContext(
- userId = input.getRequiredUserId,
- deviceId = input.clientContext.deviceId,
- userAgent = input.clientContext.userAgent,
- countryCode = input.clientContext.countryCode,
- languageCode = input.clientContext.languageCode,
- ),
- displayLocation = input.params(displayLocationParam),
- supportedLayouts = input.params(supportedLayoutsParam),
- layoutVersion = input.params(layoutVersionParam),
- excludedUserIds =
- excludedUserIdsFeature.flatMap(feature => input.features.map(_.get(feature))),
- includePromoted = Some(true),
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala
deleted file mode 100644
index a8c673a57..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.bijection.scrooge.BinaryScalaCodec
-import com.twitter.bijection.Base64String
-import com.twitter.bijection.{Injection => Serializer}
-import com.twitter.hermit.internal.thriftscala.HermitTrackingToken
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.servo.cache.ThriftSerializer
-import com.twitter.suggests.controller_data.thriftscala.ControllerData
-import com.twitter.util.Try
-import org.apache.thrift.protocol.TBinaryProtocol
-
-object WhoToFollowClientEventDetailsBuilder {
-
- val InjectionType = "WhoToFollow"
-
- private implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] =
- BinaryScalaCodec(ControllerData)
-
- private val TrackingTokenSerializer =
- new ThriftSerializer[HermitTrackingToken](HermitTrackingToken, new TBinaryProtocol.Factory())
-
- val ControllerDataSerializer: Serializer[ControllerData, String] =
- Serializer.connect[ControllerData, Array[Byte], Base64String, String]
-
- def deserializeTrackingToken(token: Option[String]): Option[HermitTrackingToken] =
- token.flatMap(t => Try(TrackingTokenSerializer.fromString(t)).toOption)
-
- def serializeControllerData(cd: ControllerData): String = ControllerDataSerializer(cd)
-}
-
-case class WhoToFollowClientEventDetailsBuilder[-Query <: PipelineQuery](
- trackingTokenFeature: Feature[_, Option[String]],
-) extends BaseClientEventDetailsBuilder[Query, UserCandidate] {
-
- override def apply(
- query: Query,
- candidate: UserCandidate,
- candidateFeatures: FeatureMap
- ): Option[ClientEventDetails] = {
- val serializedTrackingToken = candidateFeatures.getOrElse(trackingTokenFeature, None)
-
- val controllerData = WhoToFollowClientEventDetailsBuilder
- .deserializeTrackingToken(serializedTrackingToken)
- .flatMap(_.controllerData)
- .map(WhoToFollowClientEventDetailsBuilder.serializeControllerData)
-
- Some(
- ClientEventDetails(
- conversationDetails = None,
- timelinesDetails = Some(
- TimelinesDetails(
- injectionType = Some(WhoToFollowClientEventDetailsBuilder.InjectionType),
- controllerData = controllerData,
- sourceData = serializedTrackingToken)),
- articleDetails = None,
- liveEventDetails = None,
- commerceDetails = None
- ))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala
deleted file mode 100644
index 26915ceca..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.peoplediscovery.api.{thriftscala => t}
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-class WhoToFollowDependentCandidatePipelineConfig[Query <: PipelineQuery](
- override val identifier: CandidatePipelineIdentifier,
- override val enabledDeciderParam: Option[DeciderParam[Boolean]],
- override val supportedClientParam: Option[FSParam[Boolean]],
- override val alerts: Seq[Alert],
- override val gates: Seq[BaseGate[Query]],
- whoToFollowCandidateSource: PeopleDiscoveryCandidateSource,
- override val filters: Seq[Filter[Query, UserCandidate]],
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- feedbackActionInfoBuilder: Option[
- BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate]
- ],
- displayLocationParam: Param[String],
- supportedLayoutsParam: Param[Seq[String]],
- layoutVersionParam: Param[Int],
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]])
- extends DependentCandidatePipelineConfig[
- Query,
- t.GetModuleRequest,
- t.RecommendedUser,
- UserCandidate
- ] {
-
- override val candidateSource: BaseCandidateSource[t.GetModuleRequest, t.RecommendedUser] =
- whoToFollowCandidateSource
-
- override val queryTransformer: CandidatePipelineQueryTransformer[
- PipelineQuery,
- t.GetModuleRequest
- ] = WhoToFollowCandidatePipelineQueryTransformer(
- displayLocationParam = displayLocationParam,
- supportedLayoutsParam = supportedLayoutsParam,
- layoutVersionParam = layoutVersionParam,
- excludedUserIdsFeature = excludedUserIdsFeature
- )
-
- override val featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[t.RecommendedUser]
- ] = Seq(WhoToFollowResponseFeatureTransformer)
-
- override val resultTransformer: CandidatePipelineResultsTransformer[
- t.RecommendedUser,
- UserCandidate
- ] = { user => UserCandidate(user.userId) }
-
- override val decorator: Option[CandidateDecorator[Query, UserCandidate]] =
- Some(
- WhoToFollowCandidateDecorator(
- moduleDisplayTypeBuilder,
- feedbackActionInfoBuilder
- ))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala
deleted file mode 100644
index 8d95bb14b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder
-import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.Param
-import com.twitter.timelines.configapi.decider.DeciderParam
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class WhoToFollowDependentCandidatePipelineConfigBuilder @Inject() (
- whoToFollowCandidateSource: PeopleDiscoveryCandidateSource) {
-
- /**
- * Build a WhoToFollowDependentCandidatePipelineConfig
- *
- *
- * To create a regular CandidatePipelineConfig instead see [[WhoToFollowCandidatePipelineConfigBuilder]].
- *
- * @note If injected classes are needed to populate parameters in this method, consider creating a
- * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That
- * product-specific builder class can then inject everything it needs (including this class),
- * and delegate to this class's build() method within its own build() method.
- */
- def build[Query <: PipelineQuery](
- moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate],
- identifier: CandidatePipelineIdentifier = WhoToFollowCandidatePipelineConfig.identifier,
- enabledDeciderParam: Option[DeciderParam[Boolean]] = None,
- supportedClientParam: Option[FSParam[Boolean]] = None,
- alerts: Seq[Alert] = Seq.empty,
- gates: Seq[BaseGate[Query]] = Seq.empty,
- filters: Seq[Filter[Query, UserCandidate]] = Seq.empty,
- feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[
- PipelineQuery,
- UserCandidate
- ]] = None,
- displayLocationParam: Param[String] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.DisplayLocation),
- supportedLayoutsParam: Param[Seq[String]] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.SupportedLayouts),
- layoutVersionParam: Param[Int] =
- StaticParam(WhoToFollowCandidatePipelineQueryTransformer.LayoutVersion),
- excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]] = None,
- ): WhoToFollowDependentCandidatePipelineConfig[Query] =
- new WhoToFollowDependentCandidatePipelineConfig(
- identifier = identifier,
- enabledDeciderParam = enabledDeciderParam,
- supportedClientParam = supportedClientParam,
- alerts = alerts,
- gates = gates,
- whoToFollowCandidateSource = whoToFollowCandidateSource,
- filters = filters,
- moduleDisplayTypeBuilder = moduleDisplayTypeBuilder,
- feedbackActionInfoBuilder = feedbackActionInfoBuilder,
- displayLocationParam = displayLocationParam,
- supportedLayoutsParam = supportedLayoutsParam,
- layoutVersionParam = layoutVersionParam,
- excludedUserIdsFeature = excludedUserIdsFeature
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala
deleted file mode 100644
index 96cb68f1a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module
-
-import com.twitter.adserver.{thriftscala => ad}
-import com.twitter.hermit.{thriftscala => h}
-import com.twitter.peoplediscovery.api.{thriftscala => t}
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-object AdImpressionFeature extends Feature[UserCandidate, Option[ad.AdImpression]]
-object HermitContextTypeFeature extends Feature[UserCandidate, Option[h.ContextType]]
-object SocialTextFeature extends Feature[UserCandidate, Option[String]]
-object TrackingTokenFeature extends Feature[UserCandidate, Option[String]]
-object ScoreFeature extends Feature[UserCandidate, Option[Double]]
-
-object WhoToFollowResponseFeatureTransformer
- extends CandidateFeatureTransformer[t.RecommendedUser] {
-
- override val identifier: TransformerIdentifier = TransformerIdentifier("WhoToFollowResponse")
-
- override val features: Set[Feature[_, _]] =
- Set(
- AdImpressionFeature,
- HermitContextTypeFeature,
- SocialTextFeature,
- TrackingTokenFeature,
- ScoreFeature)
-
- override def transform(input: t.RecommendedUser): FeatureMap = FeatureMapBuilder()
- .add(AdImpressionFeature, input.adImpression)
- .add(HermitContextTypeFeature, input.reason.flatMap(_.contextType))
- .add(SocialTextFeature, input.socialText)
- .add(TrackingTokenFeature, input.trackingToken)
- .add(ScoreFeature, input.mlPredictionScore)
- .build()
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD
deleted file mode 100644
index f2f85ac92..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "scrooge/scrooge-serializer/src/main/scala",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "scrooge/scrooge-serializer/src/main/scala",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala
deleted file mode 100644
index d8906520a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala
+++ /dev/null
@@ -1,149 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.cursor
-
-import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor
-import com.twitter.product_mixer.component_library.model.cursor.PassThroughCursor
-import com.twitter.product_mixer.component_library.model.cursor.UnorderedBloomFilterCursor
-import com.twitter.product_mixer.component_library.model.cursor.UnorderedExcludeIdsCursor
-import com.twitter.product_mixer.component_library.{thriftscala => t}
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.scrooge.BinaryThriftStructSerializer
-import com.twitter.scrooge.ThriftStructCodec
-import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterSerializer
-import com.twitter.util.Base64UrlSafeStringEncoder
-import com.twitter.util.StringEncoder
-import com.twitter.product_mixer.core.functional_component.marshaller.response.slice.CursorTypeMarshaller
-
-/**
- * Handles serialization and deserialization for all supported generic cursors. Note that generic
- * cursors may be used for Slices or any bespoke marshalling format.
- */
-object CursorSerializer extends PipelineCursorSerializer[PipelineCursor] {
-
- private[cursor] val CursorThriftSerializer: BinaryThriftStructSerializer[
- t.ProductMixerRequestCursor
- ] =
- new BinaryThriftStructSerializer[t.ProductMixerRequestCursor] {
- override def codec: ThriftStructCodec[t.ProductMixerRequestCursor] =
- t.ProductMixerRequestCursor
- override def encoder: StringEncoder = Base64UrlSafeStringEncoder
- }
-
- override def serializeCursor(cursor: PipelineCursor): String =
- cursor match {
- case OrderedCursor(id, cursorType, gapBoundaryId) =>
- val cursorTypeMarshaller = new CursorTypeMarshaller()
- val thriftCursor = t.ProductMixerRequestCursor.OrderedCursor(
- t.OrderedCursor(
- id = id,
- cursorType = cursorType.map(cursorTypeMarshaller.apply),
- gapBoundaryId))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UnorderedExcludeIdsCursor(excludedIds) =>
- val thriftCursor = t.ProductMixerRequestCursor.UnorderedExcludeIdsCursor(
- t.UnorderedExcludeIdsCursor(excludedIds = Some(excludedIds)))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UnorderedBloomFilterCursor(longIntBloomFilter) =>
- val thriftCursor = t.ProductMixerRequestCursor.UnorderedBloomFilterCursor(
- t.UnorderedBloomFilterCursor(
- serializedLongIntBloomFilter =
- AdaptiveLongIntBloomFilterSerializer.serialize(longIntBloomFilter)
- ))
-
- CursorThriftSerializer.toString(thriftCursor)
- case PassThroughCursor(cursorValue, cursorType) =>
- val cursorTypeMarshaller = new CursorTypeMarshaller()
- val thriftCursor = t.ProductMixerRequestCursor.PassThroughCursor(
- t.PassThroughCursor(
- cursorValue = cursorValue,
- cursorType = cursorType.map(cursorTypeMarshaller.apply)
- ))
-
- CursorThriftSerializer.toString(thriftCursor)
- case _ =>
- throw PipelineFailure(IllegalStateFailure, "Unknown cursor type")
- }
-
- def deserializeOrderedCursor(cursorString: String): Option[OrderedCursor] =
- deserializeCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor
- .OrderedCursor(t.OrderedCursor(id, cursorType, gapBoundaryId))) =>
- val cursorTypeMarshaller = new CursorTypeMarshaller()
- Some(
- OrderedCursor(
- id = id,
- cursorType = cursorType.map(cursorTypeMarshaller.unmarshall),
- gapBoundaryId))
- }
- )
-
- def deserializeUnorderedExcludeIdsCursor(
- cursorString: String
- ): Option[UnorderedExcludeIdsCursor] = {
- deserializeCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor
- .UnorderedExcludeIdsCursor(t.UnorderedExcludeIdsCursor(excludedIdsOpt))) =>
- Some(UnorderedExcludeIdsCursor(excludedIds = excludedIdsOpt.getOrElse(Seq.empty)))
- }
- )
- }
-
- def deserializeUnorderedBloomFilterCursor(
- cursorString: String
- ): Option[UnorderedBloomFilterCursor] =
- deserializeCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor.UnorderedBloomFilterCursor(
- t.UnorderedBloomFilterCursor(serializedLongIntBloomFilter))) =>
- val bloomFilter = AdaptiveLongIntBloomFilterSerializer
- .deserialize(serializedLongIntBloomFilter).getOrElse(
- throw PipelineFailure(
- MalformedCursor,
- s"Failed to deserialize UnorderedBloomFilterCursor from cursor string: $cursorString")
- )
-
- Some(UnorderedBloomFilterCursor(longIntBloomFilter = bloomFilter))
- }
- )
-
- def deserializePassThroughCursor(cursorString: String): Option[PassThroughCursor] =
- deserializeCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor
- .PassThroughCursor(t.PassThroughCursor(cursorValue, cursorType))) =>
- val cursorTypeMarshaller = new CursorTypeMarshaller()
- Some(
- PassThroughCursor(
- cursorValue = cursorValue,
- cursorType = cursorType.map(cursorTypeMarshaller.unmarshall)))
- }
- )
-
- // Note that the "A" type of the PartialFunction cannot be inferred due to the thrift type not
- // being present on the PipelineCursorSerializer trait. By using this private def with the
- // deserializePf type declared, it can be inferred.
- private def deserializeCursor[Cursor <: PipelineCursor](
- cursorString: String,
- deserializePf: PartialFunction[Option[t.ProductMixerRequestCursor], Option[Cursor]]
- ): Option[Cursor] =
- PipelineCursorSerializer.deserializeCursor(
- cursorString,
- CursorThriftSerializer,
- deserializePf
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala
deleted file mode 100644
index 18c9f48a5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.cursor
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor
-import com.twitter.product_mixer.component_library.model.cursor.UrtPassThroughCursor
-import com.twitter.product_mixer.component_library.model.cursor.UrtPlaceholderCursor
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedBloomFilterCursor
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer.CursorThriftSerializer
-import com.twitter.product_mixer.component_library.{thriftscala => t}
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer.deserializeCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterSerializer
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorTypeMarshaller
-
-/**
- * Handles serialization and deserialization for all supported URT cursors
- */
-object UrtCursorSerializer extends PipelineCursorSerializer[UrtPipelineCursor] {
-
- val SerializedUrtPlaceholderCursor = CursorThriftSerializer.toString(
- t.ProductMixerRequestCursor.UrtPlaceholderCursor(t.UrtPlaceholderCursor()))
-
- val cursorTypeMarshaller = new CursorTypeMarshaller()
-
- override def serializeCursor(cursor: UrtPipelineCursor): String =
- cursor match {
- case UrtOrderedCursor(initialSortIndex, id, cursorType, gapBoundaryId) =>
- val thriftCursor = t.ProductMixerRequestCursor.UrtOrderedCursor(
- t.UrtOrderedCursor(
- initialSortIndex = initialSortIndex,
- id = id,
- cursorType.map(cursorTypeMarshaller.apply),
- gapBoundaryId = gapBoundaryId))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UrtUnorderedExcludeIdsCursor(initialSortIndex, excludedIds) =>
- val thriftCursor = t.ProductMixerRequestCursor.UrtUnorderedExcludeIdsCursor(
- t.UrtUnorderedExcludeIdsCursor(
- initialSortIndex = initialSortIndex,
- excludedIds = Some(excludedIds)))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UrtUnorderedBloomFilterCursor(initialSortIndex, longIntBloomFilter) =>
- val thriftCursor = t.ProductMixerRequestCursor.UrtUnorderedBloomFilterCursor(
- t.UrtUnorderedBloomFilterCursor(
- initialSortIndex = initialSortIndex,
- serializedLongIntBloomFilter =
- AdaptiveLongIntBloomFilterSerializer.serialize(longIntBloomFilter)
- ))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UrtPassThroughCursor(initialSortIndex, cursorValue, cursorType) =>
- val thriftCursor = t.ProductMixerRequestCursor.UrtPassThroughCursor(
- t.UrtPassThroughCursor(
- initialSortIndex = initialSortIndex,
- cursorValue = cursorValue,
- cursorType = cursorType.map(cursorTypeMarshaller.apply)
- ))
-
- CursorThriftSerializer.toString(thriftCursor)
- case UrtPlaceholderCursor() =>
- SerializedUrtPlaceholderCursor
- case _ =>
- throw PipelineFailure(IllegalStateFailure, "Unknown cursor type")
- }
-
- def deserializeOrderedCursor(cursorString: String): Option[UrtOrderedCursor] = {
- deserializeUrtCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor.UrtOrderedCursor(
- t.UrtOrderedCursor(initialSortIndex, id, cursorType, gapBoundaryId))) =>
- Some(
- UrtOrderedCursor(
- initialSortIndex = initialSortIndex,
- id = id,
- cursorType = cursorType.map(cursorTypeMarshaller.unmarshall),
- gapBoundaryId))
- }
- )
- }
-
- def deserializeUnorderedExcludeIdsCursor(
- cursorString: String
- ): Option[UrtUnorderedExcludeIdsCursor] = {
- deserializeUrtCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor.UrtUnorderedExcludeIdsCursor(
- t.UrtUnorderedExcludeIdsCursor(initialSortIndex, excludedIdsOpt))) =>
- Some(
- UrtUnorderedExcludeIdsCursor(
- initialSortIndex = initialSortIndex,
- excludedIds = excludedIdsOpt.getOrElse(Seq.empty)))
- }
- )
- }
-
- def deserializeUnorderedBloomFilterCursor(
- cursorString: String
- ): Option[UrtUnorderedBloomFilterCursor] = {
- deserializeUrtCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor.UrtUnorderedBloomFilterCursor(
- t.UrtUnorderedBloomFilterCursor(initialSortIndex, serializedLongIntBloomFilter))) =>
- val longIntBloomFilter = AdaptiveLongIntBloomFilterSerializer
- .deserialize(serializedLongIntBloomFilter).getOrElse(
- throw PipelineFailure(
- MalformedCursor,
- s"Failed to deserialize UrtUnorderedBloomFilterCursor from cursor string: $cursorString")
- )
-
- Some(
- UrtUnorderedBloomFilterCursor(
- initialSortIndex = initialSortIndex,
- longIntBloomFilter = longIntBloomFilter))
- }
- )
- }
-
- def deserializePassThroughCursor(cursorString: String): Option[UrtPassThroughCursor] = {
- deserializeUrtCursor(
- cursorString,
- {
- case Some(
- t.ProductMixerRequestCursor
- .UrtPassThroughCursor(
- t.UrtPassThroughCursor(initialSortIndex, cursorValue, cursorType))) =>
- Some(
- UrtPassThroughCursor(
- initialSortIndex = initialSortIndex,
- cursorValue = cursorValue,
- cursorType = cursorType.map(cursorTypeMarshaller.unmarshall)))
- }
- )
- }
-
- private def deserializeUrtCursor[Cursor <: PipelineCursor](
- cursorString: String,
- deserializePf: PartialFunction[Option[t.ProductMixerRequestCursor], Option[Cursor]]
- ): Option[Cursor] = {
- deserializeCursor[t.ProductMixerRequestCursor, Cursor](
- cursorString,
- CursorThriftSerializer,
- deserializePf orElse {
- case Some(t.ProductMixerRequestCursor.UrtPlaceholderCursor(t.UrtPlaceholderCursor())) =>
- // Treat submitted placeholder cursor like an initial page load
- None
- },
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD
deleted file mode 100644
index 87f51350d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala
deleted file mode 100644
index a53f410b2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice
-
-import com.twitter.product_mixer.component_library.model.candidate._
-import com.twitter.product_mixer.component_library.model.candidate.hubble.AdCreativeCandidate
-import com.twitter.product_mixer.component_library.model.candidate.hubble.AdGroupCandidate
-import com.twitter.product_mixer.component_library.model.candidate.hubble.AdUnitCandidate
-import com.twitter.product_mixer.component_library.model.candidate.hubble.CampaignCandidate
-import com.twitter.product_mixer.component_library.model.candidate.hubble.FundingSourceCandidate
-import com.twitter.product_mixer.component_library.model.candidate.suggestion.QuerySuggestionCandidate
-import com.twitter.product_mixer.component_library.model.candidate.suggestion.TypeaheadEventCandidate
-import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceBuilder
-import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorBuilder
-import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorUpdater
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedCandidateDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedCandidateDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException
-import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.slice.BaseSliceItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.slice._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Domain marshaller that generates Slices automatically for most candidates but a different
- * presentation can be provided by decorators that implement [[BaseSliceItemPresentation]]. This will
- * only be necessary in the rare case that a candidate contains more than an id. For example,
- * cursors require a value/type rather than an id.
- */
-case class SliceDomainMarshaller[-Query <: PipelineQuery](
- override val cursorBuilders: Seq[SliceCursorBuilder[Query]] = Seq.empty,
- override val cursorUpdaters: Seq[SliceCursorUpdater[Query]] = Seq.empty,
- override val identifier: DomainMarshallerIdentifier = DomainMarshallerIdentifier("Slice"))
- extends DomainMarshaller[Query, Slice]
- with SliceBuilder[Query] {
-
- override def apply(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Slice = {
- val entries = selections.map {
- case ItemCandidateWithDetails(_, Some(presentation: BaseSliceItemPresentation), _) =>
- presentation.sliceItem
- case candidateWithDetails @ ItemCandidateWithDetails(candidate, None, _) =>
- val source = candidateWithDetails.source
- candidate match {
- case candidate: BaseTopicCandidate => TopicItem(candidate.id)
- case candidate: BaseTweetCandidate => TweetItem(candidate.id)
- case candidate: BaseUserCandidate => UserItem(candidate.id)
- case candidate: TwitterListCandidate => TwitterListItem(candidate.id)
- case candidate: DMConvoSearchCandidate =>
- DMConvoSearchItem(candidate.id, candidate.lastReadableEventId)
- case candidate: DMEventCandidate =>
- DMEventItem(candidate.id)
- case candidate: DMConvoCandidate =>
- DMConvoItem(candidate.id, candidate.lastReadableEventId)
- case candidate: DMMessageSearchCandidate => DMMessageSearchItem(candidate.id)
- case candidate: QuerySuggestionCandidate =>
- TypeaheadQuerySuggestionItem(candidate.id, candidate.metadata)
- case candidate: TypeaheadEventCandidate =>
- TypeaheadEventItem(candidate.id, candidate.metadata)
- case candidate: AdUnitCandidate =>
- AdItem(candidate.id, candidate.adAccountId)
- case candidate: AdCreativeCandidate =>
- AdCreativeItem(candidate.id, candidate.adType, candidate.adAccountId)
- case candidate: AdGroupCandidate =>
- AdGroupItem(candidate.id, candidate.adAccountId)
- case candidate: CampaignCandidate =>
- CampaignItem(candidate.id, candidate.adAccountId)
- case candidate: FundingSourceCandidate =>
- FundingSourceItem(candidate.id, candidate.adAccountId)
- case candidate: CursorCandidate =>
- // Cursors must contain a cursor type which is defined by the presentation. As a result,
- // cursors are expected to be handled by the Some(presentation) case above, and must not
- // fall into this case.
- throw new UndecoratedCandidateDomainMarshallerException(candidate, source)
- case candidate =>
- throw new UnsupportedCandidateDomainMarshallerException(candidate, source)
- }
- case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _) =>
- throw new UnsupportedPresentationDomainMarshallerException(
- candidate,
- presentation,
- itemCandidateWithDetails.source)
- case moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation, _) =>
- throw new UnsupportedModuleDomainMarshallerException(
- presentation,
- moduleCandidateWithDetails.source)
- }
-
- buildSlice(query, entries)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD
deleted file mode 100644
index bb49419b4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala
deleted file mode 100644
index 0d6db99a2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Builds [[OrderedCursor]] in the Next position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Specifies whether to include the builder operation in the response
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedNextCursorBuilder[Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]](
- idSelector: PartialFunction[SliceItem, Long],
- override val includeOperation: ShouldInclude[Query] = AlwaysInclude,
- serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer)
- extends SliceCursorBuilder[Query] {
- override val cursorType: CursorType = NextCursor
-
- override def cursorValue(
- query: Query,
- entries: Seq[SliceItem]
- ): String = {
- val bottomId = entries.reverseIterator.collectFirst(idSelector)
-
- val id = bottomId.orElse(query.pipelineCursor.flatMap(_.id))
-
- val cursor = OrderedCursor(id = id, cursorType = Some(cursorType))
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala
deleted file mode 100644
index fc5b509db..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Updates an [[OrderedCursor]] in the Next position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Specifies whether to include the builder operation in the response
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedNextCursorUpdater[Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]](
- idSelector: PartialFunction[SliceItem, Long],
- override val includeOperation: ShouldInclude[Query] = AlwaysInclude,
- serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer)
- extends SliceCursorUpdaterFromUnderlyingBuilder[Query] {
- override val cursorType: CursorType = NextCursor
-
- override val underlying: OrderedNextCursorBuilder[Query] =
- OrderedNextCursorBuilder(idSelector, includeOperation, serializer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala
deleted file mode 100644
index 1136ae5ac..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Builds [[OrderedCursor]] in the Previous position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Specifies whether to include the builder operation in the response
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedPreviousCursorBuilder[
- Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]
-](
- idSelector: PartialFunction[SliceItem, Long],
- override val includeOperation: ShouldInclude[Query] = AlwaysInclude,
- serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer)
- extends SliceCursorBuilder[Query] {
- override val cursorType: CursorType = PreviousCursor
-
- override def cursorValue(
- query: Query,
- entries: Seq[SliceItem]
- ): String = {
- val topId = entries.collectFirst(idSelector)
-
- val id = topId.orElse(query.pipelineCursor.flatMap(_.id))
-
- val cursor = OrderedCursor(id = id, cursorType = Some(cursorType))
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala
deleted file mode 100644
index a8f3e8573..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Updates an [[OrderedCursor]] in the Previous position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Specifies whether to include the builder operation in the response
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedPreviousCursorUpdater[
- Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]
-](
- idSelector: PartialFunction[SliceItem, Long],
- override val includeOperation: ShouldInclude[Query] = AlwaysInclude,
- serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer)
- extends SliceCursorUpdaterFromUnderlyingBuilder[Query] {
- override val cursorType: CursorType = PreviousCursor
-
- override val underlying: OrderedPreviousCursorBuilder[Query] =
- OrderedPreviousCursorBuilder(idSelector, includeOperation, serializer)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala
deleted file mode 100644
index 7770019b2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait ShouldInclude[-Query <: PipelineQuery] {
- def apply(query: Query, items: Seq[SliceItem]): Boolean
-}
-
-object AlwaysInclude extends ShouldInclude[PipelineQuery] {
- override def apply(query: PipelineQuery, entries: Seq[SliceItem]): Boolean = true
-}
-
-object IncludeOnNonEmpty extends ShouldInclude[PipelineQuery] {
- override def apply(query: PipelineQuery, entries: Seq[SliceItem]): Boolean = entries.nonEmpty
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala
deleted file mode 100644
index fba16e5c4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem
-import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.GapCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.Slice
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceInfo
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateInMarshaller
-
-trait SliceBuilder[-Query <: PipelineQuery] {
- def cursorBuilders: Seq[SliceCursorBuilder[Query]]
- def cursorUpdaters: Seq[SliceCursorUpdater[Query]]
-
- private def containsGapCursor(items: Seq[SliceItem]): Boolean =
- items.collectFirst { case CursorItem(_, GapCursor) => () }.nonEmpty
-
- final def buildSlice(query: Query, items: Seq[SliceItem]): Slice = {
- val builtCursors = cursorBuilders.flatMap(_.build(query, items))
-
- // Iterate over the cursorUpdaters in the order they were defined. Note that each updater will
- // be passed the items updated by the previous cursorUpdater.
- val updatedItems = cursorUpdaters.foldLeft(items) { (items, cursorUpdater) =>
- cursorUpdater.update(query, items)
- } ++ builtCursors
-
- val (cursors, nonCursorItems) = updatedItems.partition(_.isInstanceOf[CursorItem])
- val nextCursor = cursors.collectFirst {
- case cursor @ CursorItem(_, NextCursor) => cursor.value
- }
- val previousCursor = cursors.collectFirst {
- case cursor @ CursorItem(_, PreviousCursor) => cursor.value
- }
-
- /**
- * Identify whether a [[GapCursor]] is present and give as much detail to point to where it came from
- * Since this is already a fatal error case for the request, its okay to be a little expensive to get
- * the best error message possible for debug purposes.
- */
- if (containsGapCursor(cursors)) {
- val errorDetails =
- if (containsGapCursor(builtCursors)) {
- "This means one of your `cursorBuilders` returned a GapCursor."
- } else if (containsGapCursor(items)) {
- "This means one of your `CandidateDecorator`s decorated a Candidate with a GapCursor."
- } else {
- "This means one of your `cursorUpdaters` returned a GapCursor."
- }
- throw PipelineFailure(
- UnexpectedCandidateInMarshaller,
- s"SliceBuilder does not support GapCursors but one was given. $errorDetails"
- )
- }
-
- Slice(
- items = nonCursorItems,
- sliceInfo = SliceInfo(previousCursor = previousCursor, nextCursor = nextCursor))
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala
deleted file mode 100644
index f033b3fe8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait SliceCursorBuilder[-Query <: PipelineQuery] {
-
- val includeOperation: ShouldInclude[Query] = AlwaysInclude
-
- def cursorValue(query: Query, items: Seq[SliceItem]): String
- def cursorType: CursorType
-
- def build(query: Query, entries: Seq[SliceItem]): Option[CursorItem] = {
- if (includeOperation(query, entries)) {
- Some(
- CursorItem(
- cursorType = cursorType,
- value = cursorValue(query, entries)
- ))
- } else None
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala
deleted file mode 100644
index c70acec39..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.slice.builder
-
-import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorUpdater.getCursorByType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object SliceCursorUpdater {
-
- def getCursorByType(
- items: Seq[SliceItem],
- cursorType: CursorType
- ): Option[CursorItem] = {
- items.collectFirst {
- case cursor: CursorItem if cursor.cursorType == cursorType => cursor
- }
- }
-}
-
-/**
- * If [[SliceCursorBuilder.includeOperation]] is true and a cursor does exist in the `items`,
- * this will run the the underlying [[SliceCursorBuilder]] with the full `items`
- * (including all cursors which may be present) then filter out only the originally
- * found [[CursorItem]] from the results). Then append the new cursor to the end of the results.
- *
- * If you have multiple cursors that need to be updated, you will need to have multiple updaters.
- *
- * If a CursorCandidate is returned by a Candidate Source, use this trait to update the Cursor
- * (if necessary) and add it to the end of the candidates list.
- */
-trait SliceCursorUpdater[-Query <: PipelineQuery] extends SliceCursorBuilder[Query] { self =>
-
- def getExistingCursor(items: Seq[SliceItem]): Option[CursorItem] = {
- getCursorByType(items, self.cursorType)
- }
-
- def update(query: Query, items: Seq[SliceItem]): Seq[SliceItem] = {
- if (includeOperation(query, items)) {
- getExistingCursor(items)
- .map { existingCursor =>
- // Safe get because includeOperation() is shared in this context
- val newCursor = build(query, items).get
-
- items.filterNot(_ == existingCursor) :+ newCursor
- }.getOrElse(items)
- } else items
- }
-}
-
-trait SliceCursorUpdaterFromUnderlyingBuilder[-Query <: PipelineQuery]
- extends SliceCursorUpdater[Query] {
- def underlying: SliceCursorBuilder[Query]
- override def cursorValue(
- query: Query,
- entries: Seq[SliceItem]
- ): String = underlying.cursorValue(query, entries)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD
deleted file mode 100644
index 8ac8b547e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala
deleted file mode 100644
index 0a622caae..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp
-
-import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageBodyBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageHeaderBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageNavBarBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urp.builder.TimelineScribeConfigBuilder
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urp._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UrpDomainMarshaller {
- val PageIdSuffix = "-Page"
-}
-
-/**
- * Domain marshaller that given the builders for the body, header and navbar will generate a URP Page
- *
- * @param pageBodyBuilder PageBody builder that generates a PageBody with the query and selections
- * @param scribeConfigBuilder Scribe Config builder that generates the configuration for scribing of the page
- * @param pageHeaderBuilder PageHeader builder that generates a PageHeader with the query and selections
- * @param pageNavBarBuilder PageNavBar builder that generates a PageNavBar with the query and selections
- * @tparam Query The type of Query that this Marshaller operates with
- */
-case class UrpDomainMarshaller[-Query <: PipelineQuery](
- pageBodyBuilder: PageBodyBuilder[Query],
- pageHeaderBuilder: Option[PageHeaderBuilder[Query]] = None,
- pageNavBarBuilder: Option[PageNavBarBuilder[Query]] = None,
- scribeConfigBuilder: Option[TimelineScribeConfigBuilder[Query]] = None,
- override val identifier: DomainMarshallerIdentifier =
- DomainMarshallerIdentifier("UnifiedRichPage"))
- extends DomainMarshaller[Query, Page] {
-
- override def apply(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Page = {
- val pageBody = pageBodyBuilder.build(query, selections)
- val pageHeader = pageHeaderBuilder.flatMap(_.build(query, selections))
- val pageNavBar = pageNavBarBuilder.flatMap(_.build(query, selections))
- val scribeConfig = scribeConfigBuilder.flatMap(_.build(query, pageBody, pageHeader, pageNavBar))
-
- Page(
- id = query.product.identifier.toString + UrpDomainMarshaller.PageIdSuffix,
- pageBody = pageBody,
- scribeConfig = scribeConfig,
- pageHeader = pageHeader,
- pageNavBar = pageNavBar
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD
deleted file mode 100644
index d22d01bf8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stringcenter/client",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stringcenter/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala
deleted file mode 100644
index 1fed528fc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp.builder
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Trait for our builder which given a query and selections will return a `PageBody`
- *
- * @tparam Query
- */
-trait PageBodyBuilder[-Query <: PipelineQuery] {
-
- def build(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): PageBody
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala
deleted file mode 100644
index aa23f44e1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp.builder
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Trait for our builder which given a query and selections will return an `Option[PageHeader]`
- *
- * @tparam Query
- */
-trait PageHeaderBuilder[-Query <: PipelineQuery] {
-
- def build(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Option[PageHeader]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala
deleted file mode 100644
index 76a3836ed..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp.builder
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Trait for our builder which given a query and selections will return an `Option[PageNavBar]`
- *
- * @tparam Query
- */
-trait PageNavBarBuilder[-Query <: PipelineQuery] {
-
- def build(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Option[PageNavBar]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala
deleted file mode 100644
index c815bf58b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticTimelineScribeConfigBuilder(
- timelineScribeConfig: TimelineScribeConfig)
- extends TimelineScribeConfigBuilder[PipelineQuery] {
-
- override def build(
- query: PipelineQuery,
- pageBody: PageBody,
- pageHeader: Option[PageHeader],
- pageNavBar: Option[PageNavBar]
- ): Option[TimelineScribeConfig] = Some(timelineScribeConfig)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala
deleted file mode 100644
index 3860552df..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urp.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Trait for our builder which given a query and page info will return an `Option[TimelineScribeConfig]`
- *
- * @tparam Query
- */
-trait TimelineScribeConfigBuilder[-Query <: PipelineQuery] {
-
- def build(
- query: Query,
- pageBody: PageBody,
- pageHeader: Option[PageHeader],
- pageNavBar: Option[PageNavBar]
- ): Option[TimelineScribeConfig]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD
deleted file mode 100644
index e9426b86a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala
deleted file mode 100644
index 28f5b2912..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt
-
-import com.twitter.product_mixer.component_library.model.candidate.ArticleCandidate
-import com.twitter.product_mixer.component_library.model.candidate.AudioSpaceCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate
-import com.twitter.product_mixer.component_library.model.candidate.UserCandidate
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.AddEntriesInstructionBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.BaseUrtMetadataBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorUpdater
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtInstructionBuilder
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedCandidateDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException
-import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Decorator that is useful for fast prototyping, as it will generate URT entries from only
- * candidate IDs (no ItemPresentations or ModulePresentations from candidate pipeline decorators
- * are required).
- */
-case class UndecoratedUrtDomainMarshaller[Query <: PipelineQuery](
- override val instructionBuilders: Seq[UrtInstructionBuilder[Query, TimelineInstruction]] =
- Seq(AddEntriesInstructionBuilder()),
- override val cursorBuilders: Seq[UrtCursorBuilder[Query]] = Seq.empty,
- override val cursorUpdaters: Seq[UrtCursorUpdater[Query]] = Seq.empty,
- override val metadataBuilder: Option[BaseUrtMetadataBuilder[Query]] = None,
- override val sortIndexStep: Int = 1,
- override val identifier: DomainMarshallerIdentifier =
- DomainMarshallerIdentifier("UndecoratedUnifiedRichTimeline"))
- extends DomainMarshaller[Query, Timeline]
- with UrtBuilder[Query, TimelineInstruction] {
-
- override def apply(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Timeline = {
- val entries = selections.map {
- case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, None, _) =>
- candidate match {
- case candidate: ArticleCandidate =>
- ArticleItem(
- id = candidate.id,
- articleSeedType = FollowingListSeed,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None,
- displayType = None,
- socialContext = None,
- )
- case candidate: AudioSpaceCandidate =>
- AudioSpaceItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None)
- case candidate: TopicCandidate =>
- TopicItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None,
- topicFunctionalityType = None,
- topicDisplayType = None
- )
- case candidate: TweetCandidate =>
- TweetItem(
- id = candidate.id,
- entryNamespace = TweetItem.TweetEntryNamespace,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None,
- isPinned = None,
- entryIdToReplace = None,
- socialContext = None,
- highlights = None,
- displayType = Tweet,
- innerTombstoneInfo = None,
- timelinesScoreInfo = None,
- hasModeratedReplies = None,
- forwardPivot = None,
- innerForwardPivot = None,
- promotedMetadata = None,
- conversationAnnotation = None,
- contextualTweetRef = None,
- prerollMetadata = None,
- replyBadge = None,
- destination = None
- )
- case candidate: TwitterListCandidate =>
- TwitterListItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None,
- displayType = None
- )
- case candidate: UserCandidate =>
- UserItem(
- id = candidate.id,
- sortIndex = None,
- clientEventInfo = None,
- feedbackActionInfo = None,
- isMarkUnread = None,
- displayType = User,
- promotedMetadata = None,
- socialContext = None,
- reactiveTriggers = None,
- enableReactiveBlending = None
- )
- case candidate =>
- throw new UnsupportedCandidateDomainMarshallerException(
- candidate,
- itemCandidateWithDetails.source)
- }
- case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _) =>
- throw new UnsupportedPresentationDomainMarshallerException(
- candidate,
- presentation,
- itemCandidateWithDetails.source)
- case moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation, _) =>
- throw new UnsupportedModuleDomainMarshallerException(
- presentation,
- moduleCandidateWithDetails.source)
- }
-
- buildTimeline(query, entries)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala
deleted file mode 100644
index 80708e90a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt
-
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ManualModuleId
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration
-import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder._
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedCandidateDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedModuleDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException
-import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException
-import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation
-import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtOperationPresentation
-import com.twitter.product_mixer.core.model.common.presentation.urt.IsDispensable
-import com.twitter.product_mixer.core.model.common.presentation.urt.WithItemTreeDisplay
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Domain marshaller that generates URT timelines automatically if the candidate pipeline decorators
- * use item and module presentations types that implement [[BaseUrtItemPresentation]] and
- * [[BaseUrtModulePresentation]], respectively to hold URT presentation data.
- */
-case class UrtDomainMarshaller[-Query <: PipelineQuery](
- override val instructionBuilders: Seq[UrtInstructionBuilder[Query, TimelineInstruction]] =
- Seq(AddEntriesInstructionBuilder()),
- override val cursorBuilders: Seq[UrtCursorBuilder[Query]] = Seq.empty,
- override val cursorUpdaters: Seq[UrtCursorUpdater[Query]] = Seq.empty,
- override val metadataBuilder: Option[BaseUrtMetadataBuilder[Query]] = None,
- override val sortIndexStep: Int = 1,
- override val identifier: DomainMarshallerIdentifier =
- DomainMarshallerIdentifier("UnifiedRichTimeline"))
- extends DomainMarshaller[Query, Timeline]
- with UrtBuilder[Query, TimelineInstruction] {
-
- override def apply(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): Timeline = {
- val initialSortIndex = getInitialSortIndex(query)
-
- val entries = selections.zipWithIndex.map {
- case (ItemCandidateWithDetails(_, Some(presentation: BaseUrtItemPresentation), _), _) =>
- presentation.timelineItem
- case (ItemCandidateWithDetails(_, Some(presentation: BaseUrtOperationPresentation), _), _) =>
- presentation.timelineOperation
- case (
- ModuleCandidateWithDetails(
- candidates,
- Some(presentation: BaseUrtModulePresentation),
- _),
- index) =>
- val moduleItems = candidates.collect {
- case ItemCandidateWithDetails(_, Some(itemPresentation: BaseUrtItemPresentation), _) =>
- buildModuleItem(itemPresentation)
- }
-
- ModuleIdGeneration(presentation.timelineModule.id) match {
- case _: AutomaticUniqueModuleId =>
- // Module IDs are unique using this method since initialSortIndex is based on time of request combined
- // with each timeline module index
- presentation.timelineModule.copy(id = initialSortIndex + index, items = moduleItems)
- case ManualModuleId(moduleId) =>
- presentation.timelineModule.copy(id = moduleId, items = moduleItems)
- }
- case (
- itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _),
- _) =>
- throw new UnsupportedPresentationDomainMarshallerException(
- candidate,
- presentation,
- itemCandidateWithDetails.source)
- case (itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, None, _), _) =>
- throw new UndecoratedCandidateDomainMarshallerException(
- candidate,
- itemCandidateWithDetails.source)
- case (
- moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation @ Some(_), _),
- _) =>
- // handles given a non `BaseUrtModulePresentation` presentation type
- throw new UnsupportedModuleDomainMarshallerException(
- presentation,
- moduleCandidateWithDetails.source)
- case (moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, None, _), _) =>
- throw new UndecoratedModuleDomainMarshallerException(moduleCandidateWithDetails.source)
- }
-
- buildTimeline(query, entries)
- }
-
- private def buildModuleItem(itemPresentation: BaseUrtItemPresentation): ModuleItem = {
- val isDispensable = itemPresentation match {
- case isDispensable: IsDispensable => Some(isDispensable.dispensable)
- case _ => None
- }
- val treeDisplay = itemPresentation match {
- case withItemTreeDisplay: WithItemTreeDisplay => withItemTreeDisplay.treeDisplay
- case _ => None
- }
- ModuleItem(
- itemPresentation.timelineItem,
- dispensable = isDispensable,
- treeDisplay = treeDisplay)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala
deleted file mode 100644
index eec2a50ea..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class AddEntriesInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (entries.nonEmpty && includeInstruction(query, entries))
- Seq(AddEntriesTimelineInstruction(entries))
- else Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala
deleted file mode 100644
index 5d19b7f04..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Build the AddEntries instruction with special handling for AddToModule entries.
- *
- * Entries which are going to be added to a module are going to be added via
- * AddToModuleInstructionBuilder, for other entries in the same response (like cursor entries) we
- * still need an AddEntriesTimelineInstruction which is going to be created by this builder.
- */
-case class AddEntriesWithAddToModuleInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val entriesToAdd = entries.filter {
- case _: TimelineModule => false
- case _ => true
- }
- if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd))
- else Seq.empty
- } else
- Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala
deleted file mode 100644
index ff5c70196..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Iterates over all the [[TimelineEntry]] passed it and creates `addEntry` entries in the URT for
- * any entries which are not pinned and not replaceable(cursors are replaceable)
- *
- * This is because pinned entries always show up in the `pinEntry` section, and replaceable entries
- * will show up in the `replaceEntry` section.
- */
-case class AddEntriesWithPinnedAndReplaceInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val entriesToAdd = entries
- .filterNot(_.isPinned.getOrElse(false))
- .filter(_.entryIdToReplace.isEmpty)
- if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd))
- else Seq.empty
- } else
- Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala
deleted file mode 100644
index 6c2e96b72..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class AddEntriesWithReplaceAndShowAlertInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val entriesToAdd = entries
- .filterNot(_.isInstanceOf[ShowAlert])
- .filter(_.entryIdToReplace.isEmpty)
- if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd))
- else Seq.empty
- } else
- Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala
deleted file mode 100644
index 64a03007e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Build the AddEntries instruction with special handling for replaceable entries.
- *
- * Entries (though almost always a single entry) with a non-empty entryIdToReplace field should be
- * collected and transformed into ReplaceEntry instructions. These should be filtered out of the
- * AddEntries instruction. We avoid doing this as part of the regular AddEntriesInstructionBuilder
- * because replacement is rare and detecting replaceable entries takes linear time.
- */
-case class AddEntriesWithReplaceInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val entriesToAdd = entries.filter(_.entryIdToReplace.isEmpty)
- if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd))
- else Seq.empty
- } else {
- Seq.empty
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala
deleted file mode 100644
index f6c742549..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Build AddEntries instruction with special handling for Covers.
- *
- * Cover Entries should be collected and transformed into ShowCover instructions. These should be
- * filtered out of the AddEntries instruction. We avoid doing this as part of the regular
- * AddEntriesInstructionBuilder because covers are used only used when using a Flip Pipeline and
- * detecting cover entries takes linear time.
- */
-case class AddEntriesWithShowCoverInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] {
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddEntriesTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val entriesToAdd = entries.filterNot(_.isInstanceOf[Cover])
- if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) else Seq.empty
- } else
- Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala
deleted file mode 100644
index 72598e20f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class AddToModuleInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, AddToModuleTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[AddToModuleTimelineInstruction] = {
- if (includeInstruction(query, entries)) {
- val moduleEntries = entries.collect {
- case module: TimelineModule => module
- }
- if (moduleEntries.nonEmpty) {
- assert(moduleEntries.size == 1, "Currently we only support appending to one module")
- moduleEntries.headOption.map { moduleEntry =>
- AddToModuleTimelineInstruction(
- moduleItems = moduleEntry.items,
- moduleEntryId = moduleEntry.entryIdentifier,
- // Currently configuring moduleItemEntryId and prepend fields are not supported.
- moduleItemEntryId = None,
- prepend = None
- )
- }
- }.toSeq
- else Seq.empty
- } else {
- Seq.empty
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD
deleted file mode 100644
index 13fee695d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD
+++ /dev/null
@@ -1,29 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "src/scala/com/twitter/search/common/util/bloomfilter",
- "stringcenter/client",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "src/scala/com/twitter/search/common/util/bloomfilter",
- "stringcenter/client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala
deleted file mode 100644
index 72325d7e8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-trait BaseUnorderedExcludeIdsBottomCursorBuilder
- extends UrtCursorBuilder[
- PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor]
- ] {
-
- def excludedIdsMaxLengthParam: Param[Int]
-
- def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long]
-
- def serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor]
-
- override val cursorType: CursorType = BottomCursor
-
- override def cursorValue(
- query: PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor],
- entries: Seq[TimelineEntry]
- ): String = {
- val excludedIdsMaxLength = query.params(excludedIdsMaxLengthParam)
- assert(excludedIdsMaxLength > 0, "Excluded IDs max length must be greater than zero")
-
- val newEntryIds = excludeEntriesCollector(entries)
- assert(
- newEntryIds.length < excludedIdsMaxLength,
- "New entry IDs length must be smaller than excluded IDs max length")
-
- val excludedIds = query.pipelineCursor
- .map(_.excludedIds ++ newEntryIds)
- .getOrElse(newEntryIds)
- .takeRight(excludedIdsMaxLength)
-
- val cursor = UrtUnorderedExcludeIdsCursor(
- initialSortIndex = nextBottomInitialSortIndex(query, entries),
- excludedIds = excludedIds
- )
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala
deleted file mode 100644
index 458c25ff5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ClearCacheTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ClearCacheInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, ClearCacheTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[ClearCacheTimelineInstruction] =
- if (includeInstruction(query, entries)) Seq(ClearCacheTimelineInstruction()) else Seq.empty
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala
deleted file mode 100644
index 368336b2e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtPassThroughCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class PassThroughCursorBuilder[
- -Query <: PipelineQuery with HasPipelineCursor[UrtPassThroughCursor]
-](
- cursorFeature: Feature[Query, String],
- override val cursorType: CursorType)
- extends UrtCursorBuilder[Query] {
-
- override val includeOperation: IncludeInstruction[Query] = { (query, _) =>
- query.features.exists(_.getOrElse(cursorFeature, "").nonEmpty)
- }
-
- override def cursorValue(
- query: Query,
- entries: Seq[TimelineEntry]
- ): String =
- UrtCursorSerializer.serializeCursor(
- UrtPassThroughCursor(
- cursorSortIndex(query, entries),
- query.features.map(_.get(cursorFeature)).getOrElse(""),
- cursorType = Some(cursorType)
- )
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala
deleted file mode 100644
index e34e7b85d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait IncludeInstruction[-Query <: PipelineQuery] { self =>
- def apply(query: Query, entries: Seq[TimelineEntry]): Boolean
-
- def inverse(): IncludeInstruction[Query] = new IncludeInstruction[Query] {
- def apply(query: Query, entries: Seq[TimelineEntry]): Boolean = !self.apply(query, entries)
- }
-}
-
-object AlwaysInclude extends IncludeInstruction[PipelineQuery] {
- override def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Boolean = true
-}
-
-object IncludeOnFirstPage extends IncludeInstruction[PipelineQuery with HasPipelineCursor[_]] {
- override def apply(
- query: PipelineQuery with HasPipelineCursor[_],
- entries: Seq[TimelineEntry]
- ): Boolean = query.isFirstPage
-}
-
-object IncludeAfterFirstPage extends IncludeInstruction[PipelineQuery with HasPipelineCursor[_]] {
- override def apply(
- query: PipelineQuery with HasPipelineCursor[_],
- entries: Seq[TimelineEntry]
- ): Boolean = !query.isFirstPage
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala
deleted file mode 100644
index a4b8d0f5b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.MarkUnreadableEntry
-
-/**
- * Build a MarkUnreadEntries instruction
- *
- * Note that this implementation currently supports top-level entries, but not module item entries.
- */
-case class MarkUnreadInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, MarkEntriesUnreadInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[MarkEntriesUnreadInstruction] = {
- if (includeInstruction(query, entries)) {
- val filteredEntries = entries.collect {
- case entry: MarkUnreadableEntry if entry.isMarkUnread.contains(true) =>
- entry.entryIdentifier
- }
- if (filteredEntries.nonEmpty) Seq(MarkEntriesUnreadInstruction(filteredEntries))
- else Seq.empty
- } else {
- Seq.empty
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala
deleted file mode 100644
index 85b7b5e47..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Builds [[UrtOrderedCursor]] in the Bottom position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Logic to determine whether or not to build the bottom cursor, which only
- * applies if gap cursors are required (e.g. Home Latest). When applicable,
- * this logic should always be the inverse of the logic used to decide
- * whether or not to build the gap cursor via [[OrderedGapCursorBuilder]],
- * since either the gap or the bottom cursor must always be returned.
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedBottomCursorBuilder[
- -Query <: PipelineQuery with HasPipelineCursor[UrtOrderedCursor]
-](
- idSelector: PartialFunction[TimelineEntry, Long],
- override val includeOperation: IncludeInstruction[Query] = AlwaysInclude,
- serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer)
- extends UrtCursorBuilder[Query] {
- override val cursorType: CursorType = BottomCursor
-
- override def cursorValue(query: Query, timelineEntries: Seq[TimelineEntry]): String = {
- val bottomId = timelineEntries.reverseIterator.collectFirst(idSelector)
-
- val id = bottomId.orElse(query.pipelineCursor.flatMap(_.id))
-
- val cursor = UrtOrderedCursor(
- initialSortIndex = nextBottomInitialSortIndex(query, timelineEntries),
- id = id,
- cursorType = Some(cursorType)
- )
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala
deleted file mode 100644
index c5136c1b7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.GapCursor
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Builds [[UrtOrderedCursor]] in the Bottom position as a Gap cursor.
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param includeOperation Logic to determine whether or not to build the gap cursor, which should
- * always be the inverse of the logic used to decide whether or not to build
- * the bottom cursor via [[OrderedBottomCursorBuilder]], since either the
- * gap or the bottom cursor must always be returned.
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedGapCursorBuilder[
- -Query <: PipelineQuery with HasPipelineCursor[UrtOrderedCursor]
-](
- idSelector: PartialFunction[TimelineEntry, Long],
- override val includeOperation: IncludeInstruction[Query],
- serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer)
- extends UrtCursorBuilder[Query] {
- override val cursorType: CursorType = GapCursor
-
- override def cursorValue(
- query: Query,
- timelineEntries: Seq[TimelineEntry]
- ): String = {
- // To determine the gap boundary, use any existing cursor gap boundary id (i.e. if submitted
- // from a previous gap cursor, else use the existing cursor id (i.e. from a previous top cursor)
- val gapBoundaryId = query.pipelineCursor.flatMap(_.gapBoundaryId).orElse {
- query.pipelineCursor.flatMap(_.id)
- }
-
- val bottomId = timelineEntries.reverseIterator.collectFirst(idSelector)
-
- val id = bottomId.orElse(gapBoundaryId)
-
- val cursor = UrtOrderedCursor(
- initialSortIndex = nextBottomInitialSortIndex(query, timelineEntries),
- id = id,
- cursorType = Some(cursorType),
- gapBoundaryId = gapBoundaryId
- )
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala
deleted file mode 100644
index 2939f8d5e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.OrderedTopCursorBuilder.TopCursorOffset
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case object OrderedTopCursorBuilder {
- // Ensure that the next initial sort index is at least 10000 entries away from top cursor's
- // current sort index. This is to ensure that the contents of the next page can be populated
- // without being assigned sort indices which conflict with that of the current page. This assumes
- // that each page will have fewer than 10000 entries.
- val TopCursorOffset = 10000L
-}
-
-/**
- * Builds [[UrtOrderedCursor]] in the Top position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param serializer Converts the cursor to an encoded string
- */
-case class OrderedTopCursorBuilder(
- idSelector: PartialFunction[UniversalNoun[_], Long],
- serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer)
- extends UrtCursorBuilder[
- PipelineQuery with HasPipelineCursor[UrtOrderedCursor]
- ] {
- override val cursorType: CursorType = TopCursor
-
- override def cursorValue(
- query: PipelineQuery with HasPipelineCursor[UrtOrderedCursor],
- timelineEntries: Seq[TimelineEntry]
- ): String = {
- val topId = timelineEntries.collectFirst(idSelector)
-
- val id = topId.orElse(query.pipelineCursor.flatMap(_.id))
-
- val cursor = UrtOrderedCursor(
- initialSortIndex = cursorSortIndex(query, timelineEntries) + TopCursorOffset,
- id = id,
- cursorType = Some(cursorType)
- )
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala
deleted file mode 100644
index 9fc4cea24..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableEntry
-
-case class PinEntryInstructionBuilder()
- extends UrtInstructionBuilder[PipelineQuery, PinEntryTimelineInstruction] {
-
- override def build(
- query: PipelineQuery,
- entries: Seq[TimelineEntry]
- ): Seq[PinEntryTimelineInstruction] = {
- // Only one entry can be pinned and the desirable behavior is to pick the entry with the highest
- // sort index in the event that multiple pinned items exist. Since the entries are already
- // sorted we can accomplish this by picking the first one.
- entries.collectFirst {
- case entry: PinnableEntry if entry.isPinned.getOrElse(false) =>
- PinEntryTimelineInstruction(entry)
- }.toSeq
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala
deleted file mode 100644
index adfe085aa..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtPlaceholderCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.PlaceholderTopCursorBuilder.DefaultPlaceholderCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-
-object PlaceholderTopCursorBuilder {
- val DefaultPlaceholderCursor = UrtPlaceholderCursor()
-}
-
-/**
- * Top cursor builder that can be used when the Product does not support paging up. The URT spec
- * requires that both bottom and top cursors always be present on each page. Therefore, if the
- * product does not support paging up, then we can use a cursor value that is not deserializable.
- * This way if the client submits a TopCursor, the backend will treat the the request as if no
- * cursor was submitted.
- */
-case class PlaceholderTopCursorBuilder(
- serializer: PipelineCursorSerializer[UrtPipelineCursor] = UrtCursorSerializer)
- extends UrtCursorBuilder[PipelineQuery with HasPipelineCursor[UrtPipelineCursor]] {
- override val cursorType: CursorType = TopCursor
-
- override def cursorValue(
- query: PipelineQuery with HasPipelineCursor[UrtPipelineCursor],
- timelineEntries: Seq[TimelineEntry]
- ): String = serializer.serializeCursor(DefaultPlaceholderCursor)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala
deleted file mode 100644
index e93553780..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Selects one or more [[TimelineEntry]] instance from the input timeline entries.
- *
- * @tparam Query The domain model for the [[PipelineQuery]] used as input.
- */
-trait EntriesToReplace[-Query <: PipelineQuery] {
- def apply(query: Query, entries: Seq[TimelineEntry]): Seq[TimelineEntry]
-}
-
-/**
- * Selects all entries with a non-empty valid entryIdToReplace.
- *
- * @note this will result in multiple [[ReplaceEntryTimelineInstruction]]s
- */
-case object ReplaceAllEntries extends EntriesToReplace[PipelineQuery] {
- def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Seq[TimelineEntry] =
- entries.filter(_.entryIdToReplace.isDefined)
-}
-
-/**
- * Selects a replaceable URT [[CursorOperation]] from the timeline entries, that matches the
- * input cursorType.
- */
-case class ReplaceUrtCursor(cursorType: CursorType) extends EntriesToReplace[PipelineQuery] {
- override def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Seq[TimelineEntry] =
- entries.collectFirst {
- case cursorOperation: CursorOperation
- if cursorOperation.cursorType == cursorType && cursorOperation.entryIdToReplace.isDefined =>
- cursorOperation
- }.toSeq
-}
-
-/**
- * Create a ReplaceEntry instruction
- *
- * @param entriesToReplace each replace instruction can contain only one entry. Users specify which
- * entry to replace using [[EntriesToReplace]]. If multiple entries are
- * specified, multiple [[ReplaceEntryTimelineInstruction]]s will be created.
- * @param includeInstruction whether the instruction should be included in the response
- */
-case class ReplaceEntryInstructionBuilder[Query <: PipelineQuery](
- entriesToReplace: EntriesToReplace[Query],
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, ReplaceEntryTimelineInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[ReplaceEntryTimelineInstruction] = {
- if (includeInstruction(query, entries))
- entriesToReplace(query, entries).map(ReplaceEntryTimelineInstruction)
- else
- Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala
deleted file mode 100644
index 678904755..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ShowAlertInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, ShowAlertInstruction] {
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[ShowAlertInstruction] = {
- if (includeInstruction(query, entries)) {
- // Currently only one Alert is supported per response
- entries.collectFirst {
- case alertEntry: ShowAlert => ShowAlertInstruction(alertEntry)
- }.toSeq
- } else Seq.empty
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala
deleted file mode 100644
index fe7e4364e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowCoverInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class ShowCoverInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends UrtInstructionBuilder[Query, ShowCoverInstruction] {
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[ShowCoverInstruction] = {
- if (includeInstruction(query, entries)) {
- // Currently only one cover is supported per response
- entries.collectFirst {
- case coverEntry: Cover => ShowCoverInstruction(coverEntry)
- }.toSeq
- } else {
- Seq.empty
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala
deleted file mode 100644
index 2b374f2d0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class StaticTimelineScribeConfigBuilder(
- timelineScribeConfig: TimelineScribeConfig)
- extends TimelineScribeConfigBuilder[PipelineQuery] {
-
- def build(
- query: PipelineQuery,
- entries: Seq[TimelineEntry]
- ): Option[TimelineScribeConfig] = Some(timelineScribeConfig)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala
deleted file mode 100644
index 0e6831ca2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.BottomTermination
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineTerminationDirection
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TopAndBottomTermination
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TopTermination
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-sealed trait TerminateInstructionBuilder[Query <: PipelineQuery]
- extends UrtInstructionBuilder[Query, TerminateTimelineInstruction] {
-
- def direction: TimelineTerminationDirection
-
- override def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[TerminateTimelineInstruction] =
- if (includeInstruction(query, entries))
- Seq(TerminateTimelineInstruction(terminateTimelineDirection = direction))
- else Seq.empty
-}
-
-case class TerminateTopInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends TerminateInstructionBuilder[Query] {
-
- override val direction = TopTermination
-}
-
-case class TerminateBottomInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends TerminateInstructionBuilder[Query] {
-
- override val direction = BottomTermination
-}
-
-case class TerminateTopAndBottomInstructionBuilder[Query <: PipelineQuery](
- override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude)
- extends TerminateInstructionBuilder[Query] {
-
- override val direction = TopAndBottomTermination
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala
deleted file mode 100644
index 98c05ac4a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Trait for our builder which given a query and entries will return an `Option[TimelineScribeConfig]`
- *
- * @tparam Query
- */
-trait TimelineScribeConfigBuilder[-Query <: PipelineQuery] {
-
- def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Option[TimelineScribeConfig]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala
deleted file mode 100644
index aeb333373..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedBloomFilterCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterBuilder
-
-/**
- * Builds [[UrtUnorderedBloomFilterCursor]] in the Bottom position
- *
- * @param idSelector Specifies the entry from which to derive the `id` field
- * @param serializer Converts the cursor to an encoded string
- */
-case class UnorderedBloomFilterBottomCursorBuilder(
- idSelector: PartialFunction[UniversalNoun[_], Long],
- serializer: PipelineCursorSerializer[UrtUnorderedBloomFilterCursor] = UrtCursorSerializer)
- extends UrtCursorBuilder[
- PipelineQuery with HasPipelineCursor[UrtUnorderedBloomFilterCursor]
- ] {
-
- override val cursorType: CursorType = BottomCursor
-
- override def cursorValue(
- query: PipelineQuery with HasPipelineCursor[UrtUnorderedBloomFilterCursor],
- entries: Seq[TimelineEntry]
- ): String = {
- val bloomFilter = query.pipelineCursor.map(_.longIntBloomFilter)
- val ids = entries.collect(idSelector)
-
- val cursor = UrtUnorderedBloomFilterCursor(
- initialSortIndex = nextBottomInitialSortIndex(query, entries),
- longIntBloomFilter = AdaptiveLongIntBloomFilterBuilder.build(ids, bloomFilter)
- )
-
- serializer.serializeCursor(cursor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala
deleted file mode 100644
index 5a25da032..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.timelines.configapi.Param
-
-/**
- * Builds [[UrtUnorderedExcludeIdsCursor]] in the Bottom position
- *
- * @param excludedIdsMaxLengthParam The maximum length of the cursor
- * @param excludeIdsSelector Specifies the entry Ids to populate on the `excludedIds` field
- * @param serializer Converts the cursor to an encoded string
- */
-case class UnorderedExcludeIdsBottomCursorBuilder(
- override val excludedIdsMaxLengthParam: Param[Int],
- excludeIdsSelector: PartialFunction[UniversalNoun[_], Long],
- override val serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor] =
- UrtCursorSerializer)
- extends BaseUnorderedExcludeIdsBottomCursorBuilder {
-
- override def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long] =
- entries.collect(excludeIdsSelector)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala
deleted file mode 100644
index 468b5076b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor
-import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer
-import com.twitter.timelines.configapi.Param
-
-/**
- * Builds [[UrtUnorderedExcludeIdsCursor]] in the Bottom position when we want to also exclude ids
- * of items inside a module. The reason we cannot use [[UnorderedExcludeIdsBottomCursorBuilder]] in
- * such case is that the excludeIdsSelector of [[UnorderedExcludeIdsBottomCursorBuilder]] is doing a
- * one to one mapping between entries and excluded ids, but in case of having a module, a module
- * entry can result in excluding a sequence of entries.
- *
- * @param excludedIdsMaxLengthParam The maximum length of the cursor
- * @param excludeIdsSelector Specifies the entry Ids to populate on the `excludedIds` field
- * @param serializer Converts the cursor to an encoded string
- */
-case class UnorderedExcludeIdsSeqBottomCursorBuilder(
- override val excludedIdsMaxLengthParam: Param[Int],
- excludeIdsSelector: PartialFunction[UniversalNoun[_], Seq[Long]],
- override val serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor] =
- UrtCursorSerializer)
- extends BaseUnorderedExcludeIdsBottomCursorBuilder {
-
- override def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long] =
- entries.collect(excludeIdsSelector).flatten
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala
deleted file mode 100644
index e47bf476b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.product_mixer.core.util.SortIndexBuilder
-
-trait UrtBuilder[-Query <: PipelineQuery, +Instruction <: TimelineInstruction] {
- private val TimelineIdSuffix = "-Timeline"
-
- def instructionBuilders: Seq[UrtInstructionBuilder[Query, Instruction]]
-
- def cursorBuilders: Seq[UrtCursorBuilder[Query]]
- def cursorUpdaters: Seq[UrtCursorUpdater[Query]]
-
- def metadataBuilder: Option[BaseUrtMetadataBuilder[Query]]
-
- // Timeline entry sort indexes will count down by this value. Values higher than 1 are useful to
- // leave room in the sequence for dynamically injecting content in between existing entries.
- def sortIndexStep: Int = 1
-
- final def buildTimeline(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Timeline = {
- val initialSortIndex = getInitialSortIndex(query)
-
- // Set the sort indexes of the entries before we pass them to the cursor builders, since many
- // cursor implementations use the sort index of the first/last entry as part of the cursor value
- val sortIndexedEntries = updateSortIndexes(initialSortIndex, entries)
-
- // Iterate over the cursorUpdaters in the order they were defined. Note that each updater will
- // be passed the timelineEntries updated by the previous cursorUpdater.
- val updatedCursorEntries: Seq[TimelineEntry] =
- cursorUpdaters.foldLeft(sortIndexedEntries) { (timelineEntries, cursorUpdater) =>
- cursorUpdater.update(query, timelineEntries)
- }
-
- val allCursoredEntries =
- updatedCursorEntries ++ cursorBuilders.flatMap(_.build(query, updatedCursorEntries))
-
- val instructions: Seq[Instruction] =
- instructionBuilders.flatMap(_.build(query, allCursoredEntries))
-
- val metadata = metadataBuilder.map(_.build(query, allCursoredEntries))
-
- Timeline(
- id = query.product.identifier.toString + TimelineIdSuffix,
- instructions = instructions,
- metadata = metadata
- )
- }
-
- final def getInitialSortIndex(query: Query): Long =
- query match {
- case cursorQuery: HasPipelineCursor[_] =>
- UrtPipelineCursor
- .getCursorInitialSortIndex(cursorQuery)
- .getOrElse(SortIndexBuilder.timeToId(query.queryTime))
- case _ => SortIndexBuilder.timeToId(query.queryTime)
- }
-
- /**
- * Updates the sort indexes in the timeline entries starting from the given initial sort index
- * value and decreasing by the value defined in the sort index step field
- *
- * @param initialSortIndex The initial value of the sort index
- * @param timelineEntries Timeline entries to update
- */
- final def updateSortIndexes(
- initialSortIndex: Long,
- timelineEntries: Seq[TimelineEntry]
- ): Seq[TimelineEntry] = {
- val indexRange =
- initialSortIndex to (initialSortIndex - (timelineEntries.size * sortIndexStep)) by -sortIndexStep
-
- // Skip any existing cursors because their sort indexes will be managed by their cursor updater.
- // If the cursors are not removed first, then the remaining entries would have a gap everywhere
- // an existing cursor was present.
- val (cursorEntries, nonCursorEntries) = timelineEntries.partition {
- case _: CursorOperation => true
- case _ => false
- }
-
- nonCursorEntries.zip(indexRange).map {
- case (entry, index) =>
- entry.withSortIndex(index)
- } ++ cursorEntries
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala
deleted file mode 100644
index 9142bbd05..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.DefaultSortIndex
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.NextPageTopCursorEntryOffset
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.UrtEntryOffset
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.GapCursor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor
-import com.twitter.product_mixer.core.pipeline.HasPipelineCursor
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor
-import com.twitter.product_mixer.core.util.SortIndexBuilder
-
-object UrtCursorBuilder {
- val NextPageTopCursorEntryOffset = 1L
- val UrtEntryOffset = 1L
- val DefaultSortIndex = (query: PipelineQuery) => SortIndexBuilder.timeToId(query.queryTime)
-}
-
-trait UrtCursorBuilder[-Query <: PipelineQuery] {
-
- val includeOperation: IncludeInstruction[Query] = AlwaysInclude
-
- def cursorType: CursorType
- def cursorValue(query: Query, entries: Seq[TimelineEntry]): String
-
- /**
- * Identifier of an *existing* timeline cursor that this new cursor would replace, if this cursor
- * is returned in a `ReplaceEntry` timeline instruction.
- *
- * Note:
- * - This id is used to populate the `entryIdToReplace` field on the URT TimelineEntry
- * generated. More details at [[CursorOperation.entryIdToReplace]].
- * - As a convention, we use the sortIndex of the cursor for its id/entryId fields. So the
- * `idToReplace` should represent the sortIndex of the existing cursor to be replaced.
- */
- def idToReplace(query: Query): Option[Long] = None
-
- def cursorSortIndex(query: Query, entries: Seq[TimelineEntry]): Long =
- (query, cursorType) match {
- case (query: PipelineQuery with HasPipelineCursor[_], TopCursor) =>
- topCursorSortIndex(query, entries)
- case (query: PipelineQuery with HasPipelineCursor[_], BottomCursor | GapCursor) =>
- bottomCursorSortIndex(query, entries)
- case _ =>
- throw new UnsupportedOperationException(
- "Automatic sort index support limited to top and bottom cursors")
- }
-
- def build(query: Query, entries: Seq[TimelineEntry]): Option[CursorOperation] = {
- if (includeOperation(query, entries)) {
- val sortIndex = cursorSortIndex(query, entries)
-
- val cursorOperation = CursorOperation(
- id = sortIndex,
- sortIndex = Some(sortIndex),
- value = cursorValue(query, entries),
- cursorType = cursorType,
- displayTreatment = None,
- idToReplace = idToReplace(query),
- )
-
- Some(cursorOperation)
- } else None
- }
-
- /**
- * Build the top cursor sort index which handles the following cases:
- * 1. When there is at least one non-cursor entry, use the first entry's sort index + UrtEntryOffset
- * 2. When there are no non-cursor entries, and initialSortIndex is not set which indicates that
- * it is the first page, use DefaultSortIndex + UrtEntryOffset
- * 3. When there are no non-cursor entries, and initialSortIndex is set which indicates that it is
- * not the first page, use the query.initialSortIndex from the passed-in cursor + UrtEntryOffset
- */
- protected def topCursorSortIndex(
- query: PipelineQuery with HasPipelineCursor[_],
- entries: Seq[TimelineEntry]
- ): Long = {
- val nonCursorEntries = entries.filter {
- case _: CursorOperation => false
- case _: CursorItem => false
- case _ => true
- }
-
- lazy val initialSortIndex =
- UrtPipelineCursor.getCursorInitialSortIndex(query).getOrElse(DefaultSortIndex(query))
-
- nonCursorEntries.headOption.flatMap(_.sortIndex).getOrElse(initialSortIndex) + UrtEntryOffset
- }
-
- /**
- * Specifies the point at which the next page's entries' sort indices will start counting.
- *
- * Note that in the case of URT, the next page's entries' does not include the top cursor. As
- * such, the value of initialSortIndex passed back in the cursor is typically the bottom cursor's
- * sort index - 2. Subtracting 2 leaves room for the next page's top cursor, which will have a
- * sort index of top entry + 1.
- */
- protected def nextBottomInitialSortIndex(
- query: PipelineQuery with HasPipelineCursor[_],
- entries: Seq[TimelineEntry]
- ): Long = {
- bottomCursorSortIndex(query, entries) - NextPageTopCursorEntryOffset - UrtEntryOffset
- }
-
- /**
- * Build the bottom cursor sort index which handles the following cases:
- * 1. When there is at least one non-cursor entry, use the last entry's sort index - UrtEntryOffset
- * 2. When there are no non-cursor entries, and initialSortIndex is not set which indicates that
- * it is the first page, use DefaultSortIndex
- * 3. When there are no non-cursor entries, and initialSortIndex is set which indicates that it is
- * not the first page, use the query.initialSortIndex from the passed-in cursor
- */
- protected def bottomCursorSortIndex(
- query: PipelineQuery with HasPipelineCursor[_],
- entries: Seq[TimelineEntry]
- ): Long = {
- val nonCursorEntries = entries.filter {
- case _: CursorOperation => false
- case _: CursorItem => false
- case _ => true
- }
-
- lazy val initialSortIndex =
- UrtPipelineCursor.getCursorInitialSortIndex(query).getOrElse(DefaultSortIndex(query))
-
- nonCursorEntries.lastOption
- .flatMap(_.sortIndex).map(_ - UrtEntryOffset).getOrElse(initialSortIndex)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala
deleted file mode 100644
index 0885ff852..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorUpdater.getCursorByType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UrtCursorUpdater {
-
- def getCursorByType(
- entries: Seq[TimelineEntry],
- cursorType: CursorType
- ): Option[CursorOperation] = {
- entries.collectFirst {
- case cursor: CursorOperation if cursor.cursorType == cursorType => cursor
- }
- }
-}
-
-// If a CursorCandidate is returned by a Candidate Source, use this trait to update that Cursor as
-// necessary (as opposed to building a new cursor which is done with the UrtCursorBuilder)
-trait UrtCursorUpdater[-Query <: PipelineQuery] extends UrtCursorBuilder[Query] { self =>
-
- def getExistingCursor(entries: Seq[TimelineEntry]): Option[CursorOperation] = {
- getCursorByType(entries, self.cursorType)
- }
-
- def update(query: Query, entries: Seq[TimelineEntry]): Seq[TimelineEntry] = {
- if (includeOperation(query, entries)) {
- getExistingCursor(entries)
- .map { existingCursor =>
- // Safe .get because includeOperation() is shared in this context
- // build() method creates a new CursorOperation. We copy over the `idToReplace`
- // from the existing cursor.
- val newCursor =
- build(query, entries).get
- .copy(idToReplace = existingCursor.idToReplace)
-
- entries.filterNot(_ == existingCursor) :+ newCursor
- }.getOrElse(entries)
- } else entries
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala
deleted file mode 100644
index ac1b9da31..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait UrtInstructionBuilder[-Query <: PipelineQuery, +Instruction <: TimelineInstruction] {
-
- def includeInstruction: IncludeInstruction[Query] = AlwaysInclude
-
- def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): Seq[Instruction]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala
deleted file mode 100644
index a59efea0c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.component_library.premarshaller.urt.builder
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stringcenter.client.StringCenter
-import com.twitter.stringcenter.client.core.ExternalString
-
-trait BaseUrtMetadataBuilder[-Query <: PipelineQuery] {
- def build(
- query: Query,
- entries: Seq[TimelineEntry]
- ): TimelineMetadata
-}
-
-case class UrtMetadataBuilder(
- title: Option[String] = None,
- scribeConfigBuilder: Option[TimelineScribeConfigBuilder[PipelineQuery]])
- extends BaseUrtMetadataBuilder[PipelineQuery] {
-
- override def build(
- query: PipelineQuery,
- entries: Seq[TimelineEntry]
- ): TimelineMetadata = TimelineMetadata(
- title = title,
- scribeConfig = scribeConfigBuilder.flatMap(_.build(query, entries))
- )
-}
-
-case class UrtMetadataStringCenterBuilder(
- titleKey: ExternalString,
- scribeConfigBuilder: Option[TimelineScribeConfigBuilder[PipelineQuery]],
- stringCenter: StringCenter)
- extends BaseUrtMetadataBuilder[PipelineQuery] {
-
- override def build(
- query: PipelineQuery,
- entries: Seq[TimelineEntry]
- ): TimelineMetadata = TimelineMetadata(
- title = Some(stringCenter.prepare(titleKey)),
- scribeConfig = scribeConfigBuilder.flatMap(_.build(query, entries))
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD
deleted file mode 100644
index ed7e90b3f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/io/grpc:grpc-netty",
- "3rdparty/jvm/io/netty:netty4-tcnative-boringssl-static",
- "3rdparty/jvm/io/opil:tensorflow-serving-client",
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/jvm/triton/inference:triton-grpc",
- "finagle-internal/finagle-grpc/src/main/scala",
- "finagle-internal/finagle-grpc/src/test/java",
- "finagle-internal/finagle-grpc/src/test/proto",
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication",
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/client",
- "finagle/finagle-http/src/main/scala",
- "finatra-internal/mtls/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "ml-serving/scala:kfserving-tfserving-converter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/triton/inference:triton-grpc",
- "finagle/finagle-http/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala
deleted file mode 100644
index ee763759c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.common
-
-import com.twitter.stitch.Stitch
-import inference.GrpcService.ModelInferRequest
-import inference.GrpcService.ModelInferResponse
-
-/**
- * MLModelInferenceClient for calling different Inference Service such as ManagedModelClient or NaviModelClient.
- */
-trait MLModelInferenceClient {
- def score(request: ModelInferRequest): Stitch[ModelInferResponse]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala
deleted file mode 100644
index cd71a072a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.common
-
-import com.twitter.finagle.Http
-import com.twitter.finagle.grpc.FinagleChannelBuilder
-import com.twitter.finagle.grpc.FutureConverters
-import com.twitter.stitch.Stitch
-import inference.GRPCInferenceServiceGrpc
-import inference.GrpcService.ModelInferRequest
-import inference.GrpcService.ModelInferResponse
-import io.grpc.ManagedChannel
-
-/**
- * Client wrapper for calling a Cortex Managed Inference Service (go/cmis) ML Model using GRPC.
- * @param httpClient Finagle HTTP Client to use for connection.
- * @param modelPath Wily path to the ML Model service (e.g. /cluster/local/role/service/instance).
- */
-case class ManagedModelClient(
- httpClient: Http.Client,
- modelPath: String)
- extends MLModelInferenceClient {
-
- private val channel: ManagedChannel =
- FinagleChannelBuilder.forTarget(modelPath).httpClient(httpClient).build()
-
- private val inferenceServiceStub = GRPCInferenceServiceGrpc.newFutureStub(channel)
-
- def score(request: ModelInferRequest): Stitch[ModelInferResponse] = {
- Stitch
- .callFuture(
- FutureConverters
- .RichListenableFuture(inferenceServiceStub.modelInfer(request)).toTwitter)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala
deleted file mode 100644
index 9dfdf7415..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.common
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Selector for choosing which Model ID/Name to use when calling an underlying ML Model Service.
- */
-trait ModelSelector[-Query <: PipelineQuery] {
- def apply(query: Query): Option[String]
-}
-
-/**
- * Simple Model ID Selector that chooses model based off of a Param object.
- * @param param ConfigAPI Param that decides the model id.
- */
-case class ParamModelSelector[Query <: PipelineQuery](param: Param[String])
- extends ModelSelector[Query] {
- override def apply(query: Query): Option[String] = Some(query.params(param))
-}
-
-/**
- * Static Selector that chooses the same model name always
- * @param modelName The model name to use.
- */
-case class StaticModelSelector(modelName: String) extends ModelSelector[PipelineQuery] {
- override def apply(query: PipelineQuery): Option[String] = Some(modelName)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala
deleted file mode 100644
index d5a5ccb50..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.common
-
-import com.twitter.finagle.Http
-import com.twitter.finagle.grpc.FinagleChannelBuilder
-import com.twitter.finagle.grpc.FutureConverters
-import com.twitter.mlserving.frontend.TFServingInferenceServiceImpl
-import com.twitter.stitch.Stitch
-import tensorflow.serving.PredictionServiceGrpc
-import inference.GrpcService.ModelInferRequest
-import inference.GrpcService.ModelInferResponse
-import io.grpc.ManagedChannel
-import io.grpc.Status
-
-/**
- * Client wrapper for calling a Navi Inference Service (go/navi).
- * @param httpClient Finagle HTTP Client to use for connection.
- * @param modelPath Wily path to the ML Model service (e.g. /s/role/service).
- */
-case class NaviModelClient(
- httpClient: Http.Client,
- modelPath: String)
- extends MLModelInferenceClient {
-
- private val channel: ManagedChannel =
- FinagleChannelBuilder
- .forTarget(modelPath)
- .httpClient(httpClient)
- // Navi enforces an authority name.
- .overrideAuthority("rustserving")
- // certain GRPC errors need to be retried.
- .enableRetryForStatus(Status.UNKNOWN)
- .enableRetryForStatus(Status.RESOURCE_EXHAUSTED)
- // this is required at channel level as mTLS is enabled at httpClient level
- .usePlaintext()
- .build()
-
- private val inferenceServiceStub = PredictionServiceGrpc.newFutureStub(channel)
-
- def score(request: ModelInferRequest): Stitch[ModelInferResponse] = {
- val tfServingRequest = TFServingInferenceServiceImpl.adaptModelInferRequest(request)
- Stitch
- .callFuture(
- FutureConverters
- .RichListenableFuture(inferenceServiceStub.predict(tfServingRequest)).toTwitter
- .map { response =>
- TFServingInferenceServiceImpl.adaptModelInferResponse(response)
- }
- )
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD
deleted file mode 100644
index 80e97e4a4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-http/src/main/scala",
- "finatra-internal/mtls/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/scala/com/twitter/ml/featurestore/lib",
- "src/thrift/com/twitter/ml/prediction_service:prediction_service-java",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala
deleted file mode 100644
index 67c85407d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cortex
-
-import com.google.protobuf.ByteString
-import com.twitter.ml.prediction_service.BatchPredictionRequest
-import com.twitter.ml.prediction_service.BatchPredictionResponse
-import com.twitter.product_mixer.component_library.scorer.common.ManagedModelClient
-import com.twitter.product_mixer.component_library.scorer.common.ModelSelector
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.datarecord.TensorDataRecordCompatible
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import inference.GrpcService
-import inference.GrpcService.ModelInferRequest
-import inference.GrpcService.ModelInferResponse
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import org.apache.thrift.TDeserializer
-import org.apache.thrift.TSerializer
-import scala.collection.JavaConverters._
-
-private[cortex] class CortexManagedDataRecordScorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _] with TensorDataRecordCompatible[_]
-](
- override val identifier: ScorerIdentifier,
- modelSignature: String,
- modelSelector: ModelSelector[Query],
- modelClient: ManagedModelClient,
- queryFeatures: FeaturesScope[QueryFeatures],
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures])
- extends Scorer[Query, Candidate] {
-
- require(resultFeatures.nonEmpty, "Result features cannot be empty")
- override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]]
-
- private val queryDataRecordAdapter = new DataRecordConverter(queryFeatures)
- private val candidatesDataRecordAdapter = new DataRecordConverter(candidateFeatures)
- private val resultDataRecordExtractor = new DataRecordExtractor(resultFeatures)
-
- private val localTSerializer = new ThreadLocal[TSerializer] {
- override protected def initialValue: TSerializer = new TSerializer()
- }
-
- private val localTDeserializer = new ThreadLocal[TDeserializer] {
- override protected def initialValue: TDeserializer = new TDeserializer()
- }
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = {
- modelClient.score(buildRequest(query, candidates)).map(buildResponse(candidates, _))
- }
-
- /**
- * Takes candidates to be scored and converts it to a ModelInferRequest that can be passed to the
- * managed ML service
- */
- private def buildRequest(
- query: Query,
- scorerCandidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModelInferRequest = {
- // Convert the feature maps to thrift data records and construct thrift request.
- val thriftDataRecords = scorerCandidates.map { candidate =>
- candidatesDataRecordAdapter.toDataRecord(candidate.features)
- }
- val batchRequest = new BatchPredictionRequest(thriftDataRecords.asJava)
- query.features.foreach { featureMap =>
- batchRequest.setCommonFeatures(queryDataRecordAdapter.toDataRecord(featureMap))
- }
- val serializedBatchRequest = localTSerializer.get().serialize(batchRequest)
-
- // Build Tensor Request
- val requestBuilder = ModelInferRequest
- .newBuilder()
-
- modelSelector.apply(query).foreach { modelName =>
- requestBuilder.setModelName(modelName) // model name in the model config
- }
-
- val inputTensorBuilder = ModelInferRequest.InferInputTensor
- .newBuilder()
- .setName("request")
- .setDatatype("UINT8")
- .addShape(serializedBatchRequest.length)
-
- val inferParameter = GrpcService.InferParameter
- .newBuilder()
- .setStringParam(modelSignature) // signature of exported tf function
- .build()
-
- requestBuilder
- .addInputs(inputTensorBuilder)
- .addRawInputContents(ByteString.copyFrom(serializedBatchRequest))
- .putParameters("signature_name", inferParameter)
- .build()
- }
-
- private def buildResponse(
- scorerCandidates: Seq[CandidateWithFeatures[Candidate]],
- response: ModelInferResponse
- ): Seq[FeatureMap] = {
-
- val responseByteString = if (response.getRawOutputContentsList.isEmpty()) {
- throw PipelineFailure(
- IllegalStateFailure,
- "Model inference response has empty raw outputContents")
- } else {
- response.getRawOutputContents(0)
- }
- val batchPredictionResponse: BatchPredictionResponse = new BatchPredictionResponse()
- localTDeserializer.get().deserialize(batchPredictionResponse, responseByteString.toByteArray)
-
- // get the prediction values from the batch prediction response
- val resultScoreMaps =
- batchPredictionResponse.predictions.asScala.map(resultDataRecordExtractor.fromDataRecord)
-
- if (resultScoreMaps.size != scorerCandidates.size) {
- throw PipelineFailure(IllegalStateFailure, "Result Size mismatched candidates size")
- }
-
- resultScoreMaps
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala
deleted file mode 100644
index 026cfa696..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cortex
-
-import com.twitter.finagle.Http
-import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.FinagleHttpClientModule
-import com.twitter.product_mixer.component_library.scorer.common.ManagedModelClient
-import com.twitter.product_mixer.component_library.scorer.common.ModelSelector
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.datarecord.TensorDataRecordCompatible
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import javax.inject.Inject
-import javax.inject.Named
-import javax.inject.Singleton
-
-@Singleton
-class CortexManagedInferenceServiceDataRecordScorerBuilder @Inject() (
- @Named(FinagleHttpClientModule) httpClient: Http.Client) {
-
- /**
- * Builds a configurable Scorer to call into your desired DataRecord-backed Cortex Managed ML Model Service.
- *
- * If your service does not bind an Http.Client implementation, add
- * [[com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule]]
- * to your server module list
- *
- * @param scorerIdentifier Unique identifier for the scorer
- * @param modelPath MLS path to model
- * @param modelSignature Model Signature Key
- * @param modelSelector [[ModelSelector]] for choosing the model name, can be an anon function.
- * @param candidateFeatures Desired candidate level feature store features to pass to the model.
- * @param resultFeatures Desired candidate level feature store features to extract from the model.
- * Since the Cortex Managed Platform always returns tensor values, the
- * feature must use a [[TensorDataRecordCompatible]].
- * @tparam Query Type of pipeline query.
- * @tparam Candidate Type of candidates to score.
- * @tparam QueryFeatures type of the query level features consumed by the scorer.
- * @tparam CandidateFeatures type of the candidate level features consumed by the scorer.
- * @tparam ResultFeatures type of the candidate level features returned by the scorer.
- */
- def build[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _] with TensorDataRecordCompatible[_]
- ](
- scorerIdentifier: ScorerIdentifier,
- modelPath: String,
- modelSignature: String,
- modelSelector: ModelSelector[Query],
- queryFeatures: FeaturesScope[QueryFeatures],
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures]
- ): Scorer[Query, Candidate] =
- new CortexManagedDataRecordScorer(
- identifier = scorerIdentifier,
- modelSignature = modelSignature,
- modelSelector = modelSelector,
- modelClient = ManagedModelClient(httpClient, modelPath),
- queryFeatures = queryFeatures,
- candidateFeatures = candidateFeatures,
- resultFeatures = resultFeatures
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala
deleted file mode 100644
index be96e78be..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cortex
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.component_library.scorer.common.MLModelInferenceClient
-import com.twitter.product_mixer.component_library.scorer.tensorbuilder.ModelInferRequestBuilder
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import com.twitter.util.logging.Logging
-import inference.GrpcService.ModelInferRequest
-import inference.GrpcService.ModelInferResponse.InferOutputTensor
-import scala.collection.convert.ImplicitConversions.`collection AsScalaIterable`
-
-private[scorer] class CortexManagedInferenceServiceTensorScorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
-](
- override val identifier: ScorerIdentifier,
- modelInferRequestBuilder: ModelInferRequestBuilder[
- Query,
- Candidate
- ],
- resultFeatureExtractors: Seq[FeatureWithExtractor[Query, Candidate, _]],
- client: MLModelInferenceClient,
- statsReceiver: StatsReceiver)
- extends Scorer[Query, Candidate]
- with Logging {
-
- require(resultFeatureExtractors.nonEmpty, "Result Extractors cannot be empty")
-
- private val managedServiceRequestFailures = statsReceiver.counter("managedServiceRequestFailures")
- override val features: Set[Feature[_, _]] =
- resultFeatureExtractors.map(_.feature).toSet.asInstanceOf[Set[Feature[_, _]]]
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = {
- val batchInferRequest: ModelInferRequest = modelInferRequestBuilder(query, candidates)
-
- val managedServiceResponse: Stitch[Seq[InferOutputTensor]] =
- client.score(batchInferRequest).map(_.getOutputsList.toSeq).onFailure { e =>
- error(s"request to ML Managed Service Failed: $e")
- managedServiceRequestFailures.incr()
- }
-
- managedServiceResponse.map { responses =>
- extractResponse(query, candidates.map(_.candidate), responses)
- }
- }
-
- def extractResponse(
- query: Query,
- candidates: Seq[Candidate],
- tensorOutput: Seq[InferOutputTensor]
- ): Seq[FeatureMap] = {
- val featureMapBuilders = candidates.map { _ => FeatureMapBuilder.apply() }
- // Extract the feature for each candidate from the tensor outputs
- resultFeatureExtractors.foreach {
- case FeatureWithExtractor(feature, extractor) =>
- val extractedValues = extractor.apply(query, tensorOutput)
- if (candidates.size != extractedValues.size) {
- throw PipelineFailure(
- IllegalStateFailure,
- s"Managed Service returned a different number of $feature than the number of candidates." +
- s"Returned ${extractedValues.size} scores but there were ${candidates.size} candidates."
- )
- }
- // Go through the extracted features list one by one and update the feature map result for each candidate.
- featureMapBuilders.zip(extractedValues).foreach {
- case (builder, value) =>
- builder.add(feature, Some(value))
- }
- }
-
- featureMapBuilders.map(_.build())
- }
-}
-
-case class FeatureWithExtractor[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any],
- ResultType
-](
- feature: Feature[Candidate, Option[ResultType]],
- featureExtractor: ModelFeatureExtractor[Query, ResultType])
-
-class UnexpectedFeatureTypeException(feature: Feature[_, _])
- extends UnsupportedOperationException(s"Unsupported Feature type passed in $feature")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala
deleted file mode 100644
index 84ef39fd7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cortex
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.component_library.scorer.common.MLModelInferenceClient
-import com.twitter.product_mixer.component_library.scorer.tensorbuilder.ModelInferRequestBuilder
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CortexManagedInferenceServiceTensorScorerBuilder @Inject() (
- statsReceiver: StatsReceiver) {
-
- /**
- * Builds a configurable Scorer to call into your desired Cortex Managed ML Model Service.
- *
- * If your service does not bind an Http.Client implementation, add
- * [[com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule]]
- * to your server module list
- *
- * @param scorerIdentifier Unique identifier for the scorer
- * @param resultFeatureExtractors The result features an their tensor extractors for each candidate.
- * @tparam Query Type of pipeline query.
- * @tparam Candidate Type of candidates to score.
- * @tparam QueryFeatures type of the query level features consumed by the scorer.
- * @tparam CandidateFeatures type of the candidate level features consumed by the scorer.
- */
- def build[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- scorerIdentifier: ScorerIdentifier,
- modelInferRequestBuilder: ModelInferRequestBuilder[
- Query,
- Candidate
- ],
- resultFeatureExtractors: Seq[FeatureWithExtractor[Query, Candidate, _]],
- client: MLModelInferenceClient
- ): Scorer[Query, Candidate] =
- new CortexManagedInferenceServiceTensorScorer(
- scorerIdentifier,
- modelInferRequestBuilder,
- resultFeatureExtractors,
- client,
- statsReceiver.scope(scorerIdentifier.name)
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala
deleted file mode 100644
index 3a44d5ceb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cortex
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import inference.GrpcService.ModelInferResponse.InferOutputTensor
-
-/**
- * Extractor defining how a Scorer should go from outputted tensors to the individual results
- * for each candidate being scored.
- *
- * @tparam Result the type of the Value being returned.
- * Users can pass in an anonymous function
- */
-trait ModelFeatureExtractor[-Query <: PipelineQuery, Result] {
- def apply(query: Query, tensorOutput: Seq[InferOutputTensor]): Seq[Result]
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel
deleted file mode 100644
index ce01a28e6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "cr-ml-ranker/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- ],
- exports = [
- "cr-ml-ranker/thrift/src/main/thrift:thrift-scala",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala
deleted file mode 100644
index 9bc1b6aae..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cr_ml_ranker
-
-import com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker.CrMlRankerCommonFeatures
-import com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker.CrMlRankerRankingConfig
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object CrMlRankerScore extends Feature[TweetCandidate, Double]
-
-/**
- * Scorer that scores tweets using the Content Recommender ML Light Ranker: http://go/cr-ml-ranker
- */
-@Singleton
-class CrMlRankerScorer @Inject() (crMlRanker: CrMlRankerScoreStitchClient)
- extends Scorer[PipelineQuery, TweetCandidate] {
-
- override val identifier: ScorerIdentifier = ScorerIdentifier("CrMlRanker")
-
- override val features: Set[Feature[_, _]] = Set(CrMlRankerScore)
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[TweetCandidate]]
- ): Stitch[Seq[FeatureMap]] = {
- val queryFeatureMap = query.features.getOrElse(FeatureMap.empty)
- val rankingConfig = queryFeatureMap.get(CrMlRankerRankingConfig)
- val commonFeatures = queryFeatureMap.get(CrMlRankerCommonFeatures)
- val userId = query.getRequiredUserId
-
- val scoresStitch = Stitch.collect(candidates.map { candidateWithFeatures =>
- crMlRanker
- .getScore(userId, candidateWithFeatures.candidate, rankingConfig, commonFeatures).map(
- _.score)
- })
- scoresStitch.map { scores =>
- scores.map { score =>
- FeatureMapBuilder()
- .add(CrMlRankerScore, score)
- .build()
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala
deleted file mode 100644
index 15e9103f1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.cr_ml_ranker
-
-import com.twitter.cr_ml_ranker.{thriftscala => t}
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.stitch.SeqGroup
-import com.twitter.stitch.Stitch
-import com.twitter.util.Future
-import com.twitter.util.Return
-import com.twitter.util.Try
-
-case class CrMlRankerResult(
- tweetId: Long,
- score: Double)
-
-class CrMlRankerScoreStitchClient(
- crMLRanker: t.CrMLRanker.MethodPerEndpoint,
- maxBatchSize: Int) {
-
- def getScore(
- userId: Long,
- tweetCandidate: BaseTweetCandidate,
- rankingConfig: t.RankingConfig,
- commonFeatures: t.CommonFeatures
- ): Stitch[CrMlRankerResult] = {
- Stitch.call(
- tweetCandidate,
- CrMlRankerGroup(
- userId = userId,
- rankingConfig = rankingConfig,
- commonFeatures = commonFeatures
- )
- )
- }
-
- private case class CrMlRankerGroup(
- userId: Long,
- rankingConfig: t.RankingConfig,
- commonFeatures: t.CommonFeatures)
- extends SeqGroup[BaseTweetCandidate, CrMlRankerResult] {
-
- override val maxSize: Int = maxBatchSize
-
- override protected def run(
- tweetCandidates: Seq[BaseTweetCandidate]
- ): Future[Seq[Try[CrMlRankerResult]]] = {
- val crMlRankerCandidates =
- tweetCandidates.map { tweetCandidate =>
- t.RankingCandidate(
- tweetId = tweetCandidate.id,
- hydrationContext = Some(
- t.FeatureHydrationContext.HomeHydrationContext(t
- .HomeFeatureHydrationContext(tweetAuthor = None)))
- )
- }
-
- val thriftResults = crMLRanker.getRankedResults(
- t.RankingRequest(
- requestContext = t.RankingRequestContext(
- userId = userId,
- config = rankingConfig
- ),
- candidates = crMlRankerCandidates,
- commonFeatures = commonFeatures.commonFeatures
- )
- )
-
- thriftResults.map { response =>
- response.scoredTweets.map { scoredTweet =>
- Return(
- CrMlRankerResult(
- tweetId = scoredTweet.tweetId,
- score = scoredTweet.score
- )
- )
- }
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD
deleted file mode 100644
index 355427143..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD
+++ /dev/null
@@ -1,42 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "cortex-deepbird/thrift/src/main/thrift:thrift-java",
- "finagle/finagle-http/src/main/scala",
- "finatra-internal/mtls/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "scrooge/scrooge-serializer",
- "src/java/com/twitter/ml/api:api-base",
- "src/java/com/twitter/ml/common/base",
- "src/java/com/twitter/ml/prediction/core",
- "src/thrift/com/twitter/ml/prediction_service:prediction_service-java",
- "src/thrift/com/twitter/ml/prediction_service:prediction_service-scala",
- "twml/runtime/src/main/scala/com/twitter/deepbird/runtime/prediction_engine",
- ],
- exports = [
- "cortex-deepbird/thrift/src/main/thrift:thrift-java",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/java/com/twitter/ml/prediction/core",
- "src/thrift/com/twitter/ml/prediction_service:prediction_service-java",
- "twml/runtime/src/main/scala/com/twitter/deepbird/runtime/prediction_engine",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala
deleted file mode 100644
index 59b1f29bf..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.deepbird
-
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.ml.prediction_service.BatchPredictionRequest
-import com.twitter.ml.prediction_service.BatchPredictionResponse
-import com.twitter.cortex.deepbird.thriftjava.{ModelSelector => TModelSelector}
-import com.twitter.ml.api.DataRecord
-import com.twitter.product_mixer.component_library.scorer.common.ModelSelector
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import scala.collection.JavaConverters._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import com.twitter.util.Future
-
-abstract class BaseDeepbirdV2Scorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _]
-](
- override val identifier: ScorerIdentifier,
- modelIdSelector: ModelSelector[Query],
- queryFeatures: FeaturesScope[QueryFeatures],
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures])
- extends Scorer[Query, Candidate] {
-
- private val queryDataRecordConverter = new DataRecordConverter(queryFeatures)
- private val candidateDataRecordConverter = new DataRecordConverter(candidateFeatures)
- private val resultDataRecordExtractor = new DataRecordExtractor(resultFeatures)
-
- require(resultFeatures.nonEmpty, "Result features cannot be empty")
- override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]]
- def getBatchPredictions(
- request: BatchPredictionRequest,
- modelSelector: TModelSelector
- ): Future[BatchPredictionResponse]
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = {
- // Convert all candidate feature maps to java datarecords then to scala datarecords.
- val thriftCandidateDataRecords = candidates.map { candidate =>
- candidateDataRecordConverter.toDataRecord(candidate.features)
- }
-
- val request = new BatchPredictionRequest(thriftCandidateDataRecords.asJava)
-
- // Convert the query feature map to data record if available.
- query.features.foreach { featureMap =>
- request.setCommonFeatures(queryDataRecordConverter.toDataRecord(featureMap))
- }
-
- val modelSelector = modelIdSelector
- .apply(query).map { id =>
- val selector = new TModelSelector()
- selector.setId(id)
- selector
- }.orNull
-
- Stitch.callFuture(getBatchPredictions(request, modelSelector)).map { response =>
- val dataRecords = Option(response.predictions).map(_.asScala).getOrElse(Seq.empty)
- buildResults(candidates, dataRecords)
- }
- }
-
- private def buildResults(
- candidates: Seq[CandidateWithFeatures[Candidate]],
- dataRecords: Seq[DataRecord]
- ): Seq[FeatureMap] = {
- if (dataRecords.size != candidates.size) {
- throw PipelineFailure(IllegalStateFailure, "Result Size mismatched candidates size")
- }
-
- dataRecords.map { resultDataRecord =>
- resultDataRecordExtractor.fromDataRecord(resultDataRecord)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala
deleted file mode 100644
index 330706490..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.deepbird
-
-import com.twitter.cortex.deepbird.{thriftjava => t}
-import com.twitter.ml.prediction_service.BatchPredictionRequest
-import com.twitter.ml.prediction_service.BatchPredictionResponse
-import com.twitter.product_mixer.component_library.scorer.common.ModelSelector
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.util.Future
-
-/**
- * Configurable Scorer that calls any Deepbird Prediction Service thrift.
- * @param identifier Unique identifier for the scorer
- * @param predictionService The Prediction Thrift Service
- * @param modelSelector Model ID Selector to decide which model to select, can also be represented
- * as an anonymous function: { query: Query => Some("Ex") }
- * @param queryFeatures The Query Features to convert and pass to the deepbird model.
- * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model.
- * @param resultFeatures The Candidate features returned by the model.
- * @tparam Query Type of pipeline query.
- * @tparam Candidate Type of candidates to score.
- * @tparam QueryFeatures type of the query level features consumed by the scorer.
- * @tparam CandidateFeatures type of the candidate level features consumed by the scorer.
- * @tparam ResultFeatures type of the candidate level features returned by the scorer.
- */
-case class DeepbirdV2PredictionServerScorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _]
-](
- override val identifier: ScorerIdentifier,
- predictionService: t.DeepbirdPredictionService.ServiceToClient,
- modelSelector: ModelSelector[Query],
- queryFeatures: FeaturesScope[QueryFeatures],
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures])
- extends BaseDeepbirdV2Scorer[
- Query,
- Candidate,
- QueryFeatures,
- CandidateFeatures,
- ResultFeatures
- ](identifier, modelSelector, queryFeatures, candidateFeatures, resultFeatures) {
-
- override def getBatchPredictions(
- request: BatchPredictionRequest,
- modelSelector: t.ModelSelector
- ): Future[BatchPredictionResponse] =
- predictionService.batchPredictFromModel(request, modelSelector)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala
deleted file mode 100644
index c60651be9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.deepbird
-
-import com.twitter.ml.prediction.core.PredictionEngine
-import com.twitter.ml.prediction_service.PredictionRequest
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Scorer that locally loads a Deepbird model.
- * @param identifier Unique identifier for the scorer
- * @param predictionEngine Prediction Engine hosting the Deepbird model.
- * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model.
- * @param resultFeatures The Candidate features returned by the model.
- * @tparam Query Type of pipeline query.
- * @tparam Candidate Type of candidates to score.
- * @tparam QueryFeatures type of the query level features consumed by the scorer.
- * @tparam CandidateFeatures type of the candidate level features consumed by the scorer.
- * @tparam ResultFeatures type of the candidate level features returned by the scorer.
- */
-class LollyPredictionEngineScorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _]
-](
- override val identifier: ScorerIdentifier,
- predictionEngine: PredictionEngine,
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures])
- extends Scorer[Query, Candidate] {
-
- private val dataRecordAdapter = new DataRecordConverter(candidateFeatures)
-
- require(resultFeatures.nonEmpty, "Result features cannot be empty")
- override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]]
-
- private val resultsDataRecordExtractor = new DataRecordExtractor(resultFeatures)
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = {
- val featureMaps = candidates.map { candidateWithFeatures =>
- val dataRecord = dataRecordAdapter.toDataRecord(candidateWithFeatures.features)
- val predictionResponse = predictionEngine.apply(new PredictionRequest(dataRecord), true)
- resultsDataRecordExtractor.fromDataRecord(predictionResponse.getPrediction)
- }
- Stitch.value(featureMaps)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala
deleted file mode 100644
index 847d62c89..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.deepbird
-
-import com.twitter.cortex.deepbird.runtime.prediction_engine.TensorflowPredictionEngine
-import com.twitter.cortex.deepbird.thriftjava.ModelSelector
-import com.twitter.ml.prediction_service.BatchPredictionRequest
-import com.twitter.ml.prediction_service.BatchPredictionResponse
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.util.Future
-
-/**
- * Configurable Scorer that calls a TensorflowPredictionEngine.
- * @param identifier Unique identifier for the scorer
- * @param tensorflowPredictionEngine The TensorFlow Prediction Engine
- * @param queryFeatures The Query Features to convert and pass to the deepbird model.
- * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model.
- * @param resultFeatures The Candidate features returned by the model.
- * @tparam Query Type of pipeline query.
- * @tparam Candidate Type of candidates to score.
- * @tparam QueryFeatures type of the query level features consumed by the scorer.
- * @tparam CandidateFeatures type of the candidate level features consumed by the scorer.
- * @tparam ResultFeatures type of the candidate level features returned by the scorer.
- */
-class TensorflowPredictionEngineScorer[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- QueryFeatures <: BaseDataRecordFeature[Query, _],
- CandidateFeatures <: BaseDataRecordFeature[Candidate, _],
- ResultFeatures <: BaseDataRecordFeature[Candidate, _]
-](
- override val identifier: ScorerIdentifier,
- tensorflowPredictionEngine: TensorflowPredictionEngine,
- queryFeatures: FeaturesScope[QueryFeatures],
- candidateFeatures: FeaturesScope[CandidateFeatures],
- resultFeatures: Set[ResultFeatures])
- extends BaseDeepbirdV2Scorer[
- Query,
- Candidate,
- QueryFeatures,
- CandidateFeatures,
- ResultFeatures
- ](
- identifier,
- { _: Query =>
- None
- },
- queryFeatures,
- candidateFeatures,
- resultFeatures) {
-
- override def getBatchPredictions(
- request: BatchPredictionRequest,
- modelSelector: ModelSelector
- ): Future[BatchPredictionResponse] = tensorflowPredictionEngine.getBatchPrediction(request)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD
deleted file mode 100644
index af69ac038..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala
deleted file mode 100644
index 3185ce019..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.param_gated
-
-import com.twitter.product_mixer.component_library.scorer.param_gated.ParamGatedScorer.IdentifierPrefix
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[scorer]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this [[scorer]] on and off
- * @param scorer the underlying [[scorer]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class ParamGatedScorer[-Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- enabledParam: Param[Boolean],
- scorer: Scorer[Query, Result])
- extends Scorer[Query, Result]
- with Conditionally[Query] {
- override val identifier: ScorerIdentifier = ScorerIdentifier(
- IdentifierPrefix + scorer.identifier.name)
- override val alerts: Seq[Alert] = scorer.alerts
- override val features: Set[Feature[_, _]] = scorer.features
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(query, scorer, query.params(enabledParam))
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Result]]
- ): Stitch[Seq[FeatureMap]] = scorer(query, candidates)
-}
-
-object ParamGatedScorer {
- val IdentifierPrefix = "ParamGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD
deleted file mode 100644
index af69ac038..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala
deleted file mode 100644
index 3309fbdca..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.qualityfactor_gated
-
-import com.twitter.product_mixer.component_library.scorer.qualityfactor_gated.QualityFactorGatedScorer.IdentifierPrefix
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[scorer]] with [[Conditionally]] based on quality factor value and threshold
- *
- * @param qualityFactorThreshold quliaty factor threshold that turn off the scorer
- * @param pipelineIdentifier identifier of the pipeline that quality factor is based on
- * @param scorer the underlying [[scorer]] to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- * @tparam Result The type of the candidates
- */
-case class QualityFactorGatedScorer[
- -Query <: PipelineQuery with HasQualityFactorStatus,
- Result <: UniversalNoun[Any]
-](
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorThresholdParam: Param[Double],
- scorer: Scorer[Query, Result])
- extends Scorer[Query, Result]
- with Conditionally[Query] {
-
- override val identifier: ScorerIdentifier = ScorerIdentifier(
- IdentifierPrefix + scorer.identifier.name)
-
- override val alerts: Seq[Alert] = scorer.alerts
-
- override val features: Set[Feature[_, _]] = scorer.features
-
- override def onlyIf(query: Query): Boolean =
- Conditionally.and(
- query,
- scorer,
- query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params(
- qualityFactorThresholdParam))
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Result]]
- ): Stitch[Seq[FeatureMap]] = scorer(query, candidates)
-}
-
-object QualityFactorGatedScorer {
- val IdentifierPrefix = "QualityFactorGated"
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD
deleted file mode 100644
index e18c39662..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ml/api:embedding-scala",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala
deleted file mode 100644
index bbdf2b5c6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object BooleanInferInputTensorBuilder extends InferInputTensorBuilder[Boolean] {
- def apply(
- featureName: String,
- featureValues: Seq[Boolean]
- ): Seq[InferInputTensor] = {
- val tensorShape = Seq(featureValues.size, 1)
- InferInputTensorBuilder.buildBoolInferInputTensor(featureName, featureValues, tensorShape)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala
deleted file mode 100644
index 8b36c514f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object BytesInferInputTensorBuilder extends InferInputTensorBuilder[String] {
- def apply(
- featureName: String,
- featureValues: Seq[String]
- ): Seq[InferInputTensor] = {
- val tensorShape = Seq(featureValues.size, 1)
- InferInputTensorBuilder.buildBytesInferInputTensor(featureName, featureValues, tensorShape)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala
deleted file mode 100644
index ed7c28cdb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.twitter.ml.api.thriftscala.FloatTensor
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.ModelFeatureName
-import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-class CandidateInferInputTensorBuilder[-Candidate <: UniversalNoun[Any], +Value](
- builder: InferInputTensorBuilder[Value],
- features: Set[_ <: Feature[Candidate, _] with ModelFeatureName]) {
- def apply(
- candidates: Seq[CandidateWithFeatures[Candidate]],
- ): Seq[InferInputTensor] = {
- features.flatMap { feature =>
- val featureValues: Seq[Value] = feature match {
- case feature: FeatureStoreV1CandidateFeature[_, Candidate, _, Value] =>
- candidates.map(_.features.getFeatureStoreV1CandidateFeature(feature))
- case feature: FeatureStoreV1QueryFeature[_, _, _] =>
- throw new UnexpectedFeatureTypeException(feature)
- case feature: FeatureWithDefaultOnFailure[Candidate, Value] =>
- candidates.map(_.features.getTry(feature).toOption.getOrElse(feature.defaultValue))
- case feature: Feature[Candidate, Value] =>
- candidates.map(_.features.get(feature))
- }
- builder.apply(feature.featureName, featureValues)
- }.toSeq
- }
-}
-
-case class CandidateBooleanInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, Boolean] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, Boolean](
- BooleanInferInputTensorBuilder,
- features)
-
-case class CandidateBytesInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, String] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, String](
- BytesInferInputTensorBuilder,
- features)
-
-case class CandidateFloat32InferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, _ <: AnyVal] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, AnyVal](
- Float32InferInputTensorBuilder,
- features)
-
-case class CandidateFloatTensorInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, FloatTensor] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, FloatTensor](
- FloatTensorInferInputTensorBuilder,
- features)
-
-case class CandidateInt64InferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, _ <: AnyVal] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, AnyVal](
- Int64InferInputTensorBuilder,
- features)
-
-case class CandidateSparseMapInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]](
- features: Set[_ <: Feature[Candidate, Option[Map[Int, Double]]] with ModelFeatureName])
- extends CandidateInferInputTensorBuilder[Candidate, Option[Map[Int, Double]]](
- SparseMapInferInputTensorBuilder,
- features)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala
deleted file mode 100644
index a6fb674bc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object Float32InferInputTensorBuilder extends InferInputTensorBuilder[AnyVal] {
-
- private def toFloat(x: AnyVal): Float = {
- x match {
- case y: Float => y
- case y: Int => y.toFloat
- case y: Long => y.toFloat
- case y: Double => y.toFloat
- case y => throw new UnexpectedDataTypeException(y, this)
- }
- }
-
- def apply(
- featureName: String,
- featureValues: Seq[AnyVal]
- ): Seq[InferInputTensor] = {
- val tensorShape = Seq(featureValues.size, 1)
- InferInputTensorBuilder.buildFloat32InferInputTensor(
- featureName,
- featureValues.map(toFloat),
- tensorShape)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala
deleted file mode 100644
index d1f4f021f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.twitter.ml.api.thriftscala.FloatTensor
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object FloatTensorInferInputTensorBuilder extends InferInputTensorBuilder[FloatTensor] {
-
- private[tensorbuilder] def extractTensorShape(featureValues: Seq[FloatTensor]): Seq[Int] = {
- val headFloatTensor = featureValues.head
- if (headFloatTensor.shape.isEmpty) {
- Seq(
- featureValues.size,
- featureValues.head.floats.size
- )
- } else {
- Seq(featureValues.size) ++ headFloatTensor.shape.get.map(_.toInt)
- }
- }
-
- def apply(
- featureName: String,
- featureValues: Seq[FloatTensor]
- ): Seq[InferInputTensor] = {
- if (featureValues.isEmpty) throw new EmptyFloatTensorException(featureName)
- val tensorShape = extractTensorShape(featureValues)
- val floatValues = featureValues.flatMap { featureValue =>
- featureValue.floats.map(_.toFloat)
- }
- InferInputTensorBuilder.buildFloat32InferInputTensor(featureName, floatValues, tensorShape)
- }
-}
-class EmptyFloatTensorException(featureName: String)
- extends RuntimeException(s"FloatTensor in feature $featureName is empty!")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala
deleted file mode 100644
index e83fea4e2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.google.protobuf.ByteString
-import com.twitter.product_mixer.core.feature.Feature
-import inference.GrpcService.InferTensorContents
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-// This class contains most of common versions at Twitter, but in the future we can add more:
-// https://github.com/kserve/kserve/blob/master/docs/predict-api/v2/required_api.md#tensor-data-1
-
-trait InferInputTensorBuilder[Value] {
-
- def apply(
- featureName: String,
- featureValues: Seq[Value]
- ): Seq[InferInputTensor]
-
-}
-
-object InferInputTensorBuilder {
-
- def checkTensorShapeMatchesValueLength(
- featureName: String,
- featureValues: Seq[Any],
- tensorShape: Seq[Int]
- ): Unit = {
- val featureValuesSize = featureValues.size
- val tensorShapeSize = tensorShape.product
- if (featureValuesSize != tensorShapeSize) {
- throw new FeatureValuesAndShapeMismatchException(
- featureName,
- featureValuesSize,
- tensorShapeSize)
- }
- }
-
- def buildBoolInferInputTensor(
- featureName: String,
- featureValues: Seq[Boolean],
- tensorShape: Seq[Int]
- ): Seq[InferInputTensor] = {
-
- checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape)
-
- val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName)
- tensorShape.foreach { shape =>
- inputTensorBuilder.addShape(shape)
- }
- val inputTensor = inputTensorBuilder
- .setDatatype("BOOL")
- .setContents {
- val contents = InferTensorContents.newBuilder()
- featureValues.foreach { featureValue =>
- contents.addBoolContents(featureValue)
- }
- contents
- }
- .build()
- Seq(inputTensor)
- }
-
- def buildBytesInferInputTensor(
- featureName: String,
- featureValues: Seq[String],
- tensorShape: Seq[Int]
- ): Seq[InferInputTensor] = {
-
- checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape)
-
- val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName)
- tensorShape.foreach { shape =>
- inputTensorBuilder.addShape(shape)
- }
- val inputTensor = inputTensorBuilder
- .setDatatype("BYTES")
- .setContents {
- val contents = InferTensorContents.newBuilder()
- featureValues.foreach { featureValue =>
- val featureValueBytes = ByteString.copyFromUtf8(featureValue)
- contents.addByteContents(featureValueBytes)
- }
- contents
- }
- .build()
- Seq(inputTensor)
- }
-
- def buildFloat32InferInputTensor(
- featureName: String,
- featureValues: Seq[Float],
- tensorShape: Seq[Int]
- ): Seq[InferInputTensor] = {
-
- checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape)
-
- val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName)
- tensorShape.foreach { shape =>
- inputTensorBuilder.addShape(shape)
- }
- val inputTensor = inputTensorBuilder
- .setDatatype("FP32")
- .setContents {
- val contents = InferTensorContents.newBuilder()
- featureValues.foreach { featureValue =>
- contents.addFp32Contents(featureValue.floatValue)
- }
- contents
- }
- .build()
- Seq(inputTensor)
- }
-
- def buildInt64InferInputTensor(
- featureName: String,
- featureValues: Seq[Long],
- tensorShape: Seq[Int]
- ): Seq[InferInputTensor] = {
-
- checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape)
-
- val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName)
- tensorShape.foreach { shape =>
- inputTensorBuilder.addShape(shape)
- }
- val inputTensor = inputTensorBuilder
- .setDatatype("INT64")
- .setContents {
- val contents = InferTensorContents.newBuilder()
- featureValues.foreach { featureValue =>
- contents.addInt64Contents(featureValue)
- }
- contents
- }
- .build()
- Seq(inputTensor)
- }
-}
-
-class UnexpectedFeatureTypeException(feature: Feature[_, _])
- extends UnsupportedOperationException(s"Unsupported Feature type passed in $feature")
-
-class FeatureValuesAndShapeMismatchException(
- featureName: String,
- featureValuesSize: Int,
- tensorShapeSize: Int)
- extends UnsupportedOperationException(
- s"Feature $featureName has mismatching FeatureValues (size: $featureValuesSize) and TensorShape (size: $tensorShapeSize)!")
-
-class UnexpectedDataTypeException[T](value: T, builder: InferInputTensorBuilder[_])
- extends UnsupportedOperationException(
- s"Unsupported data type ${value} passed in at ${builder.getClass.toString}")
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala
deleted file mode 100644
index 9743317d8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.twitter.ml.featurestore.lib.Discrete
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object Int64InferInputTensorBuilder extends InferInputTensorBuilder[AnyVal] {
-
- private def toLong(x: AnyVal): Long = {
- x match {
- case y: Int => y.toLong
- case y: Long => y
- case y: Discrete => y.value
- case y => throw new UnexpectedDataTypeException(y, this)
- }
- }
- def apply(
- featureName: String,
- featureValues: Seq[AnyVal]
- ): Seq[InferInputTensor] = {
- val tensorShape = Seq(featureValues.size, 1)
- InferInputTensorBuilder.buildInt64InferInputTensor(
- featureName,
- featureValues.map(toLong),
- tensorShape)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala
deleted file mode 100644
index e37c145fb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.twitter.product_mixer.component_library.scorer.common.ModelSelector
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import inference.GrpcService.InferParameter
-import inference.GrpcService.ModelInferRequest
-import scala.collection.JavaConverters._
-
-class ModelInferRequestBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]](
- queryInferInputTensorBuilders: Seq[QueryInferInputTensorBuilder[Query, Any]],
- candidateInferInputTensorBuilders: Seq[
- CandidateInferInputTensorBuilder[Candidate, Any]
- ],
- modelSignatureName: String,
- modelSelector: ModelSelector[Query]) {
-
- private val modelSignature: InferParameter =
- InferParameter.newBuilder().setStringParam(modelSignatureName).build()
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]],
- ): ModelInferRequest = {
- val inferRequest = ModelInferRequest
- .newBuilder()
- .putParameters("signature_name", modelSignature)
- modelSelector.apply(query).foreach { modelName =>
- inferRequest.setModelName(modelName)
- }
- queryInferInputTensorBuilders.foreach { builder =>
- inferRequest.addAllInputs(builder(query).asJava)
- }
- candidateInferInputTensorBuilders.foreach { builder =>
- inferRequest.addAllInputs(builder(candidates).asJava)
- }
- inferRequest.build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala
deleted file mode 100644
index 4415d61a1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import com.twitter.ml.api.thriftscala.FloatTensor
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.ModelFeatureName
-import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-class QueryInferInputTensorBuilder[-Query <: PipelineQuery, +Value](
- builder: InferInputTensorBuilder[Value],
- features: Set[_ <: Feature[Query, _] with ModelFeatureName]) {
- def apply(query: Query): Seq[InferInputTensor] = {
- val featureMap = query.features.getOrElse(FeatureMap.empty)
- features.flatMap { feature =>
- val queryFeatureValue: Value = feature match {
- case feature: FeatureStoreV1QueryFeature[Query, _, Value] =>
- featureMap.getFeatureStoreV1QueryFeature(feature)
- case feature: FeatureStoreV1CandidateFeature[Query, _, _, Value] =>
- throw new UnexpectedFeatureTypeException(feature)
- case feature: FeatureWithDefaultOnFailure[Query, Value] =>
- featureMap.getTry(feature).toOption.getOrElse(feature.defaultValue)
- case feature: Feature[Query, Value] =>
- featureMap.get(feature)
- }
- builder.apply(feature.featureName, Seq(queryFeatureValue))
- }.toSeq
- }
-}
-
-case class QueryBooleanInferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, Boolean] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, Boolean](BooleanInferInputTensorBuilder, features)
-
-case class QueryBytesInferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, String] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, String](BytesInferInputTensorBuilder, features)
-
-case class QueryFloat32InferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, _ <: AnyVal] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, AnyVal](Float32InferInputTensorBuilder, features)
-
-case class QueryFloatTensorInferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, FloatTensor] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, FloatTensor](
- FloatTensorInferInputTensorBuilder,
- features)
-
-case class QueryInt64InferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, _ <: AnyVal] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, AnyVal](Int64InferInputTensorBuilder, features)
-
-case class QuerySparseMapInferInputTensorBuilder[-Query <: PipelineQuery](
- features: Set[_ <: Feature[Query, Option[Map[Int, Double]]] with ModelFeatureName])
- extends QueryInferInputTensorBuilder[Query, Option[Map[Int, Double]]](
- SparseMapInferInputTensorBuilder,
- features)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala
deleted file mode 100644
index 038ff90db..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tensorbuilder
-
-import inference.GrpcService.InferTensorContents
-import inference.GrpcService.ModelInferRequest.InferInputTensor
-
-case object SparseMapInferInputTensorBuilder
- extends InferInputTensorBuilder[Option[Map[Int, Double]]] {
-
- private final val batchFeatureNameSuffix: String = "batch"
- private final val keyFeatureNameSuffix: String = "key"
- private final val valueFeatureNameSuffix: String = "value"
-
- def apply(
- featureName: String,
- featureValues: Seq[Option[Map[Int, Double]]]
- ): Seq[InferInputTensor] = {
- val batchIdsTensorContents = InferTensorContents.newBuilder()
- val sparseKeysTensorContents = InferTensorContents.newBuilder()
- val sparseValuesTensorContents = InferTensorContents.newBuilder()
- featureValues.zipWithIndex.foreach {
- case (featureValueOption, batchIndex) =>
- featureValueOption.foreach { featureValue =>
- featureValue.foreach {
- case (sparseKey, sparseValue) =>
- batchIdsTensorContents.addInt64Contents(batchIndex.toLong)
- sparseKeysTensorContents.addInt64Contents(sparseKey.toLong)
- sparseValuesTensorContents.addFp32Contents(sparseValue.floatValue)
- }
- }
- }
-
- val batchIdsInputTensor = InferInputTensor
- .newBuilder()
- .setName(Seq(featureName, batchFeatureNameSuffix).mkString("_"))
- .addShape(batchIdsTensorContents.getInt64ContentsCount)
- .addShape(1)
- .setDatatype("INT64")
- .setContents(batchIdsTensorContents)
- .build()
-
- val sparseKeysInputTensor = InferInputTensor
- .newBuilder()
- .setName(Seq(featureName, keyFeatureNameSuffix).mkString("_"))
- .addShape(sparseKeysTensorContents.getInt64ContentsCount)
- .addShape(1)
- .setDatatype("INT64")
- .setContents(sparseKeysTensorContents)
- .build()
-
- val sparseValuesInputTensor = InferInputTensor
- .newBuilder()
- .setName(Seq(featureName, valueFeatureNameSuffix).mkString("_"))
- .addShape(sparseValuesTensorContents.getFp32ContentsCount)
- .addShape(1)
- .setDatatype("FP32")
- .setContents(sparseValuesTensorContents)
- .build()
-
- Seq(batchIdsInputTensor, sparseKeysInputTensor, sparseValuesInputTensor)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel
deleted file mode 100644
index e306724d0..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala",
- "src/thrift/com/twitter/timelinescorer:thrift-scala",
- "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala",
- "strato/config/columns/ml/featureStore:featureStore-strato-client",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala
deleted file mode 100644
index 69a803c90..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tweet_tlx
-
-import com.twitter.ml.featurestore.timelines.thriftscala.TimelineScorerScoreView
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.strato.catalog.Fetch.Result
-import com.twitter.strato.generated.client.ml.featureStore.TimelineScorerTweetScoresV1ClientColumn
-import com.twitter.timelinescorer.thriftscala.v1
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Score Tweets via Timeline Scorer (TLX) Strato API
- *
- * @note This results in an additional hop through Strato Server
- * @note This is the [[Scorer]] version of
- * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]]
- */
-@Singleton
-class TweetTLXStratoScorer @Inject() (column: TimelineScorerTweetScoresV1ClientColumn)
- extends Scorer[PipelineQuery, TweetCandidate] {
-
- override val identifier: ScorerIdentifier = ScorerIdentifier("TweetTLX")
-
- override val features: Set[Feature[_, _]] = Set(TLXScore)
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[TweetCandidate]]
- ): Stitch[Seq[FeatureMap]] = query.getOptionalUserId match {
- case Some(userId) => getScoredTweetsFromTLX(userId, candidates.map(_.candidate))
- case _ =>
- val defaultFeatureMap = FeatureMapBuilder().add(TLXScore, None).build()
- Stitch.value(candidates.map(_ => defaultFeatureMap))
- }
-
- def getScoredTweetsFromTLX(
- userId: Long,
- tweetCandidates: Seq[TweetCandidate]
- ): Stitch[Seq[FeatureMap]] = Stitch.collect(tweetCandidates.map { candidate =>
- column.fetcher
- .fetch(candidate.id, TimelineScorerScoreView(Some(userId)))
- .map {
- case Result(Some(v1.ScoredTweet(_, score, _, _)), _) =>
- FeatureMapBuilder()
- .add(TLXScore, score)
- .build()
- case fetchResult => throw new Exception(s"Invalid response from TLX: ${fetchResult.v}")
- }
- })
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala
deleted file mode 100644
index e53f3dcfc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.component_library.scorer.tweet_tlx
-
-import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelinescorer.thriftscala.v1
-import com.twitter.timelinescorer.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * @note This Feature is shared with
- * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]]
- * and
- * [[com.twitter.product_mixer.component_library.scorer.tweet_tlx.TweetTLXStratoScorer]]
- * as the these components should not be used at the same time by the same Product
- */
-object TLXScore extends FeatureWithDefaultOnFailure[TweetCandidate, Option[Double]] {
- override val defaultValue = None
-}
-
-/**
- * Score Tweets via Timeline Scorer (TLX) Thrift API
- *
- * @note This is the [[Scorer]] version of
- * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]]
- */
-@Singleton
-class TweetTLXThriftScorer @Inject() (timelineScorerClient: t.TimelineScorer.MethodPerEndpoint)
- extends Scorer[PipelineQuery, TweetCandidate] {
-
- override val identifier: ScorerIdentifier = ScorerIdentifier("TLX")
-
- override val features: Set[Feature[_, _]] = Set(TLXScore)
-
- override def apply(
- query: PipelineQuery,
- candidates: Seq[CandidateWithFeatures[TweetCandidate]]
- ): Stitch[Seq[FeatureMap]] = {
- val userId = query.getOptionalUserId
- val tweetScoringQuery = v1.TweetScoringQuery(
- predictionPipeline = v1.PredictionPipeline.Recap,
- tweetIds = candidates.map(_.candidate.id))
-
- val tweetScoringRequest = t.TweetScoringRequest.V1(
- v1.TweetScoringRequest(
- tweetScoringRequestContext = Some(v1.TweetScoringRequestContext(userId = userId)),
- tweetScoringQueries = Some(Seq(tweetScoringQuery)),
- retrieveFeatures = Some(false)
- ))
-
- Stitch.callFuture(timelineScorerClient.getTweetScores(tweetScoringRequest)).map {
- case t.TweetScoringResponse.V1(response) =>
- val tweetIdScoreMap = response.tweetScoringResults
- .flatMap {
- _.headOption.map {
- _.scoredTweets.flatMap(tweet => tweet.tweetId.map(_ -> tweet.score))
- }
- }.getOrElse(Seq.empty).toMap
-
- candidates.map { candidateWithFeatures =>
- val score = tweetIdScoreMap.getOrElse(candidateWithFeatures.candidate.id, None)
- FeatureMapBuilder()
- .add(TLXScore, score)
- .build()
-
- }
- case t.TweetScoringResponse.UnknownUnionField(field) =>
- throw new UnsupportedOperationException(s"Unknown response type: ${field.field.name}")
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD
deleted file mode 100644
index c07a21e65..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD
+++ /dev/null
@@ -1,47 +0,0 @@
-scala_library(
- name = "insert_append_results",
- sources = ["InsertAppendResults.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
-)
-
-scala_library(
- sources = [
- "!InsertAppendResults.scala",
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ":insert_append_results",
- "3rdparty/jvm/com/google/inject:guice",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
- exports = [
- ":insert_append_results",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala
deleted file mode 100644
index d50394a2b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-/**
- * Given a [[CandidateWithDetails]] return the corresponding [[Bucket]]
- * it should be associated with when used in a `pattern` or `ratio`
- * in [[InsertAppendPatternResults]] or [[InsertAppendRatioResults]]
- */
-trait Bucketer[Bucket] {
- def apply(candidateWithDetails: CandidateWithDetails): Bucket
-}
-
-object Bucketer {
-
- /** A [[Bucketer]] that buckets by [[CandidateWithDetails.source]] */
- val ByCandidateSource: Bucketer[CandidatePipelineIdentifier] =
- (candidateWithDetails: CandidateWithDetails) => candidateWithDetails.source
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala
deleted file mode 100644
index 2ef321cd6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.IsPinnedFeature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSources
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition
-
-/**
- * Once a pair of duplicate candidates has been found we need to someone 'resolve' the duplication.
- * This may be as simple as picking whichever candidate came first (see [[PickFirstCandidateMerger]]
- * but this strategy could mean losing important candidate information. Candidates might, for
- * example, have different features. [[CandidateMergeStrategy]] lets you define a custom behavior
- * for resolving duplication to help support these more nuanced situations.
- */
-trait CandidateMergeStrategy {
- def apply(
- existingCandidate: ItemCandidateWithDetails,
- newCandidate: ItemCandidateWithDetails
- ): ItemCandidateWithDetails
-}
-
-/**
- * Keep whichever candidate was encountered first.
- */
-object PickFirstCandidateMerger extends CandidateMergeStrategy {
- override def apply(
- existingCandidate: ItemCandidateWithDetails,
- newCandidate: ItemCandidateWithDetails
- ): ItemCandidateWithDetails = existingCandidate
-}
-
-/**
- * Keep the candidate encountered first but combine all candidate feature maps.
- */
-object CombineFeatureMapsCandidateMerger extends CandidateMergeStrategy {
- override def apply(
- existingCandidate: ItemCandidateWithDetails,
- newCandidate: ItemCandidateWithDetails
- ): ItemCandidateWithDetails = {
- // Prepend new because list set keeps insertion order, and last operations in ListSet are O(1)
- val mergedCandidateSourceIdentifiers =
- newCandidate.features.get(CandidateSources) ++ existingCandidate.features
- .get(CandidateSources)
- val mergedCandidatePipelineIdentifiers =
- newCandidate.features.get(CandidatePipelines) ++ existingCandidate.features
- .get(CandidatePipelines)
-
- // the unitary features are pulled from the existing candidate as explained above, while
- // Set Features are merged/accumulated.
- val mergedCommonFeatureMap = FeatureMapBuilder()
- .add(CandidatePipelines, mergedCandidatePipelineIdentifiers)
- .add(CandidateSources, mergedCandidateSourceIdentifiers)
- .add(CandidateSourcePosition, existingCandidate.sourcePosition)
- .build()
-
- existingCandidate.copy(features =
- existingCandidate.features ++ newCandidate.features ++ mergedCommonFeatureMap)
- }
-}
-
-/**
- * Keep the pinnable candidate. For cases where we are dealing with duplicate entries across
- * different candidate types, such as different sub-classes of
- * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]], we will
- * prioritize the candidate with [[IsPinnedFeature]] because it contains additional information
- * needed for the positioning of a pinned entry on a timeline.
- */
-object PickPinnedCandidateMerger extends CandidateMergeStrategy {
- override def apply(
- existingCandidate: ItemCandidateWithDetails,
- newCandidate: ItemCandidateWithDetails
- ): ItemCandidateWithDetails =
- Seq(existingCandidate, newCandidate)
- .collectFirst {
- case candidate @ ItemCandidateWithDetails(_: BaseTweetCandidate, _, features)
- if features.getTry(IsPinnedFeature).toOption.contains(true) =>
- candidate
- }.getOrElse(existingCandidate)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala
deleted file mode 100644
index f73b9bd37..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Compute a position for inserting a specific candidate into the result sequence originally provided to the Selector.
- * If a `None` is returned, the Selector using this would not insert that candidate into the result.
- */
-trait CandidatePositionInResults[-Query <: PipelineQuery] {
- def apply(
- query: Query,
- candidate: CandidateWithDetails,
- result: Seq[CandidateWithDetails]
- ): Option[Int]
-}
-
-object PromptCandidatePositionInResults extends CandidatePositionInResults[PipelineQuery] {
- override def apply(
- query: PipelineQuery,
- candidate: CandidateWithDetails,
- result: Seq[CandidateWithDetails]
- ): Option[Int] = candidate match {
- case ItemCandidateWithDetails(candidate, _, _) =>
- candidate match {
- case relevancePromptCandidate: RelevancePromptCandidate => relevancePromptCandidate.position
- case _ => None
- }
- // not supporting ModuleCandidateWithDetails right now as RelevancePromptCandidate shouldn't be in a module
- case _ => None
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala
deleted file mode 100644
index 44c92826f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-
-/**
- * [[DropSelector]] detects duplicates by looking for candidates with the same key. A key can be
- * anything but is typically derived from a candidate's id and class. This approach is not always
- * appropriate. For example, two candidate sources might both return different sub-classes of
- * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]] resulting in
- * them not being treated as duplicates.
- */
-trait DeduplicationKey[Key] {
- def apply(candidate: ItemCandidateWithDetails): Key
-}
-
-/**
- * Use candidate id and class to determine duplicates.
- */
-object IdAndClassDuplicationKey extends DeduplicationKey[(String, Class[_ <: UniversalNoun[Any]])] {
- def apply(item: ItemCandidateWithDetails): (String, Class[_ <: UniversalNoun[Any]]) =
- (item.candidate.id.toString, item.candidate.getClass)
-}
-
-/**
- * Use candidate id to determine duplicates.
- * This should be used instead of [[IdAndClassDuplicationKey]] in order to deduplicate across
- * different candidate types, such as different implementations of
- * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]].
- */
-object IdDuplicationKey extends DeduplicationKey[String] {
- def apply(item: ItemCandidateWithDetails): String = item.candidate.id.toString
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala
deleted file mode 100644
index a6c239151..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Drops all Candidates on the `remainingCandidates` side which are in the [[pipelineScope]]
- *
- * This is typically used as a placeholder when templating out a new pipeline or
- * as a simple filter to drop candidates based only on the [[CandidateScope]]
- */
-case class DropAllCandidates(override val pipelineScope: CandidateScope = AllPipelines)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val PartitionedCandidates(inScope, outOfScope) = pipelineScope.partition(remainingCandidates)
-
- SelectorResult(remainingCandidates = outOfScope, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala
deleted file mode 100644
index e52956ad3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Keep only the first instance of a candidate in the `remainingCandidates` as determined by comparing
- * the contained candidate ID and class type. Subsequent matching instances will be dropped. For
- * more details, see DropSelector#dropDuplicates
- *
- * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name)
- * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one)
- *
- * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored.
- * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored.
- *
- * @example if `remainingCandidates`
- * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)`
- * then the output candidates will be `Seq(sourceA_Id1, sourceA_Id2, sourceB_id3, sourceC_id4)`
- */
-case class DropDuplicateCandidates(
- override val pipelineScope: CandidateScope = AllPipelines,
- duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey,
- mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val dedupedCandidates = dropDuplicates(
- pipelineScope = pipelineScope,
- candidates = remainingCandidates,
- duplicationKey = duplicationKey,
- mergeStrategy = mergeStrategy)
-
- SelectorResult(remainingCandidates = dedupedCandidates, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala
deleted file mode 100644
index 8c2c0002b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector._
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object DropDuplicateModuleItemCandidates {
-
- /**
- * Limit the number of module item candidates (for 1 or more modules) from a certain candidate
- * source. See [[DropDuplicateModuleItemCandidates]] for more details.
- *
- * @param candidatePipeline pipelines on which to run the selector
- *
- * @note Scala doesn't allow overloaded methods with default arguments. Users wanting to customize
- * the de-dupe logic should use the default constructor. We could provide multiple
- * constructors but that seemed more confusing (five ways to instantiate the selector) or not
- * necessarily less verbose (if we picked specific use-cases rather than trying to support
- * everything).
- */
- def apply(candidatePipeline: CandidatePipelineIdentifier) = new DropDuplicateModuleItemCandidates(
- SpecificPipeline(candidatePipeline),
- IdAndClassDuplicationKey,
- PickFirstCandidateMerger)
-
- def apply(candidatePipelines: Set[CandidatePipelineIdentifier]) =
- new DropDuplicateModuleItemCandidates(
- SpecificPipelines(candidatePipelines),
- IdAndClassDuplicationKey,
- PickFirstCandidateMerger)
-}
-
-/**
- * Limit the number of module item candidates (for 1 or more modules) from certain candidate
- * pipelines.
- *
- * This acts like a [[DropDuplicateCandidates]] but for modules in `remainingCandidates`
- * from any of the provided [[candidatePipelines]]. Similar to [[DropDuplicateCandidates]], it
- * keeps only the first instance of a candidate within a module as determined by comparing
- * the contained candidate ID and class type.
- *
- * @param pipelineScope pipeline scope on which to run the selector
- * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name)
- * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one)
- *
- * For example, if a candidatePipeline returned 5 modules each
- * containing duplicate items in the candidate pool, then the module items in each of the
- * 5 modules will be filtered to the unique items within each module.
- *
- * Another example is if you have 2 modules each with the same items as the other,
- * it won't deduplicate across modules.
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class DropDuplicateModuleItemCandidates(
- override val pipelineScope: CandidateScope,
- duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey,
- mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val remainingCandidatesLimited = remainingCandidates.map {
- case module: ModuleCandidateWithDetails if pipelineScope.contains(module) =>
- // this applies to all candidates in a module, even if they are from a different
- // candidate source, which can happen if items are added to a module during selection
- module.copy(candidates = dropDuplicates(
- pipelineScope = AllPipelines,
- candidates = module.candidates,
- duplicationKey = duplicationKey,
- mergeStrategy = mergeStrategy))
- case candidate => candidate
- }
-
- SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala
deleted file mode 100644
index bf15b3b5d..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Keep only the first instance of a candidate in the `result` as determined by comparing
- * the contained candidate ID and class type. Subsequent matching instances will be dropped. For
- * more details, see DropSelector#dropDuplicates
- *
- * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name)
- * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one)
- *
- * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored.
- * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored.
- *
- * @example if `result`
- * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)`
- * then the output result will be `Seq(sourceA_Id1, sourceA_Id2, sourceB_id3, sourceC_id4)`
- */
-case class DropDuplicateResults(
- duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey,
- mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger)
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = AllPipelines
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val dedupedResults = dropDuplicates(
- pipelineScope = pipelineScope,
- candidates = result,
- duplicationKey = duplicationKey,
- mergeStrategy = mergeStrategy)
-
- SelectorResult(remainingCandidates = remainingCandidates, result = dedupedResults)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala
deleted file mode 100644
index fe893fbc3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Predicate which will be applied to each candidate. True indicates that the candidate will be
- * kept.
- */
-trait ShouldKeepCandidate {
- def apply(candidateWithDetails: CandidateWithDetails): Boolean
-}
-
-object DropFilteredCandidates {
- def apply(candidatePipeline: CandidatePipelineIdentifier, filter: ShouldKeepCandidate) =
- new DropFilteredCandidates(SpecificPipeline(candidatePipeline), filter)
-
- def apply(candidatePipelines: Set[CandidatePipelineIdentifier], filter: ShouldKeepCandidate) =
- new DropFilteredCandidates(SpecificPipelines(candidatePipelines), filter)
-}
-
-/**
- * Limit candidates from certain candidates sources to those which satisfy the provided predicate.
- */
-case class DropFilteredCandidates(
- override val pipelineScope: CandidateScope,
- filter: ShouldKeepCandidate)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val candidatesUpdated = remainingCandidates.filter { candidate =>
- if (pipelineScope.contains(candidate)) filter.apply(candidate)
- else true
- }
-
- SelectorResult(remainingCandidates = candidatesUpdated, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala
deleted file mode 100644
index 5a9b0f410..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object DropFilteredModuleItemCandidates {
- def apply(candidatePipeline: CandidatePipelineIdentifier, filter: ShouldKeepCandidate) =
- new DropFilteredModuleItemCandidates(SpecificPipeline(candidatePipeline), filter)
-
- def apply(candidatePipelines: Set[CandidatePipelineIdentifier], filter: ShouldKeepCandidate) =
- new DropFilteredModuleItemCandidates(SpecificPipelines(candidatePipelines), filter)
-}
-
-/**
- * Limit candidates in modules from certain candidates sources to those which satisfy
- * the provided predicate.
- *
- * This acts like a [[DropFilteredCandidates]] but for modules in `remainingCandidates`
- * from any of the provided [[candidatePipelines]].
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class DropFilteredModuleItemCandidates(
- override val pipelineScope: CandidateScope,
- filter: ShouldKeepCandidate)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val candidatesUpdated = remainingCandidates.map {
- case module: ModuleCandidateWithDetails if pipelineScope.contains(module) =>
- // this applies to all candidates in a module, even if they are from a different
- // candidate source, which can happen if items are added to a module during selection
- module.copy(candidates = module.candidates.filter(filter.apply))
- case candidate => candidate
- }
-
- SelectorResult(remainingCandidates = candidatesUpdated, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala
deleted file mode 100644
index 4982ac49a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-trait MaxSelector[-Query <: PipelineQuery] {
- def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Int
-}
-
-object DropMaxCandidates {
-
- /**
- * A [[DropMaxCandidates]] Selector based on a [[Param]] applied to a single candidate pipeline
- */
- def apply[Query <: PipelineQuery](
- candidatePipeline: CandidatePipelineIdentifier,
- maxSelectionsParam: Param[Int]
- ) = new DropMaxCandidates[Query](
- SpecificPipeline(candidatePipeline),
- (query, _, _) => query.params(maxSelectionsParam))
-
- /**
- * A [[DropMaxCandidates]] Selector based on a [[Param]] with multiple candidate pipelines
- */
- def apply[Query <: PipelineQuery](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- maxSelectionsParam: Param[Int]
- ) = new DropMaxCandidates[Query](
- SpecificPipelines(candidatePipelines),
- (query, _, _) => query.params(maxSelectionsParam))
-
- /**
- * A [[DropMaxCandidates]] Selector based on a [[Param]] that applies to a [[CandidateScope]]
- */
- def apply[Query <: PipelineQuery](
- pipelineScope: CandidateScope,
- maxSelectionsParam: Param[Int]
- ) = new DropMaxCandidates[Query](pipelineScope, (query, _, _) => query.params(maxSelectionsParam))
-}
-
-/**
- * Limit the number of item and module (not items inside modules) candidates from the
- * specified pipelines based on the value provided by the [[MaxSelector]]
- *
- * For example, if value from the [[MaxSelector]] is 3, and a candidatePipeline returned 10 items
- * in the candidate pool, then these items will be reduced to the first 3 items. Note that to
- * update the ordering of the candidates, an UpdateCandidateOrderingSelector may be used prior to
- * using this Selector.
- *
- * Another example, if the [[MaxSelector]] value is 3, and a candidatePipeline returned 10 modules
- * in the candidate pool, then these will be reduced to the first 3 modules. The items inside the
- * modeles will not be affected by this selector. To control the number of items inside modules see
- * [[DropMaxModuleItemCandidates]].
- */
-case class DropMaxCandidates[-Query <: PipelineQuery](
- override val pipelineScope: CandidateScope,
- maxSelector: MaxSelector[Query])
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val maxSelections = maxSelector(query, remainingCandidates, result)
- assert(maxSelections > 0, "Max selections must be greater than zero")
-
- val remainingCandidatesLimited =
- DropSelector.takeUntil(maxSelections, remainingCandidates, pipelineScope)
-
- SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala
deleted file mode 100644
index f343d0e97..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Limit the number of module item candidates (for 1 or more modules) from a certain candidate
- * source.
- *
- * For example, if maxModuleItemsParam is 3, and a candidatePipeline returned 1 module containing 10
- * items in the candidate pool, then these module items will be reduced to the first 3 module items.
- * Note that to update the ordering of the candidates, an UpdateModuleItemsCandidateOrderingSelector
- * may be used prior to using this selector.
- *
- * Another example, if maxModuleItemsParam is 3, and a candidatePipeline returned 5 modules each
- * containing 10 items in the candidate pool, then the module items in each of the 5 modules will be
- * reduced to the first 3 module items.
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class DropMaxModuleItemCandidates(
- candidatePipeline: CandidatePipelineIdentifier,
- maxModuleItemsParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val maxModuleItemSelections = query.params(maxModuleItemsParam)
- assert(maxModuleItemSelections > 0, "Max module item selections must be greater than zero")
-
- val remainingCandidatesLimited = remainingCandidates.map {
- case module: ModuleCandidateWithDetails if pipelineScope.contains(module) =>
- // this applies to all candidates in a module, even if they are from a different
- // candidate source which can happen if items are added to a module during selection
- module.copy(candidates = DropSelector.takeUntil(maxModuleItemSelections, module.candidates))
- case candidate => candidate
- }
-
- SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala
deleted file mode 100644
index d5c655390..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Limit the number of results
- *
- * For example, if maxResultsParam is 3, and the results contain 10 items, then these items will be
- * reduced to the first 3 selected items. Note that the ordering of results is determined by the
- * selector configuration.
- *
- * Another example, if maxResultsParam is 3, and the results contain 10 modules, then these will be
- * reduced to the first 3 modules. The items inside the modules will not be affected by this
- * selector.
- */
-case class DropMaxResults(
- maxResultsParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = AllPipelines
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val maxResults = query.params(maxResultsParam)
- assert(maxResults > 0, "Max results must be greater than zero")
-
- val resultUpdated = DropSelector.takeUntil(maxResults, result)
-
- SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala
deleted file mode 100644
index 18f8989d8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Drop the module from the `result` if it doesn't contain enough item candidates.
- *
- * For example, for a given module, if minResultsParam is 3, and the results contain 2 items,
- * then that module will be entirely dropped from the results.
- */
-case class DropModuleTooFewModuleItemResults(
- candidatePipeline: CandidatePipelineIdentifier,
- minModuleItemsParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val minModuleItemSelections = query.params(minModuleItemsParam)
- assert(minModuleItemSelections > 0, "Min results must be greater than zero")
-
- val updatedResults = result.filter {
- case module: ModuleCandidateWithDetails
- if pipelineScope.contains(module) && module.candidates.count { candidateWithDetails =>
- !candidateWithDetails.candidate.isInstanceOf[CursorCandidate]
- } < minModuleItemSelections =>
- false
- case _ => true
- }
-
- SelectorResult(remainingCandidates = remainingCandidates, result = updatedResults)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala
deleted file mode 100644
index 4bbfbe076..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Keep only the candidates in `remainingCandidates` that appear multiple times.
- * This ignores modules and cursors from being removed.
- *
- * @param duplicationKey how to generate the key used to identify duplicate candidates
- *
- * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored.
- * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored.
- *
- * @example if `remainingCandidates`
- * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)`
- * then the output result will be `Seq(sourceA_Id1, sourceA_Id2)`
- */
-case class DropNonDuplicateCandidates(
- override val pipelineScope: CandidateScope,
- duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val duplicateCandidates = dropNonDuplicates(
- pipelineScope = pipelineScope,
- candidates = remainingCandidates,
- duplicationKey = duplicationKey)
-
- SelectorResult(remainingCandidates = duplicateCandidates, result = result)
- }
-
- /**
- * Identify and keep candidates using the supplied key extraction and merger functions. By default
- * this will keep only candidates that appear multiple times as determined by comparing
- * the contained candidate ID and class type. Candidates appearing only once will be dropped.
- *
- * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored.
- * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored.
- *
- * @param candidates which may have elements to drop
- * @param duplicationKey how to generate a key for a candidate for identifying duplicates
- */
- private[this] def dropNonDuplicates[Candidate <: CandidateWithDetails, Key](
- pipelineScope: CandidateScope,
- candidates: Seq[Candidate],
- duplicationKey: DeduplicationKey[Key],
- ): Seq[Candidate] = {
- // Here we are checking if each candidate has multiple appearances or not
- val isCandidateADuplicate: Map[Key, Boolean] = candidates
- .collect {
- case item: ItemCandidateWithDetails
- if pipelineScope.contains(item) && !item.candidate.isInstanceOf[CursorCandidate] =>
- item
- }.groupBy(duplicationKey(_))
- .mapValues(_.length > 1)
-
- candidates.filter {
- case item: ItemCandidateWithDetails =>
- isCandidateADuplicate.getOrElse(duplicationKey(item), true)
- case _: ModuleCandidateWithDetails => true
- case _ => false
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala
deleted file mode 100644
index 036f91bf8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Limit candidates to the first candidate source in the provided orthogonalCandidatePipelines
- * seq that has candidates in the candidate pool. For the subsequent candidate sources in the seq,
- * remove their candidates from the candidate pool.
- *
- * @example if [[orthogonalCandidatePipelines]] is `Seq(D, A, C)`, and the remaining candidates
- * component identifiers are `Seq(A, A, A, B, B, C, C, D, D, D)`, then `Seq(B, B, D, D, D)` will remain
- * in the candidate pool.
- *
- * @example if [[orthogonalCandidatePipelines]] is `Seq(D, A, C)`, and the remaining candidates
- * component identifiers are `Seq(A, A, A, B, B, C, C)`, then `Seq(A, A, A, B, B)` will remain
- * in the candidate pool.
- */
-case class DropOrthogonalCandidates(
- orthogonalCandidatePipelines: Seq[CandidatePipelineIdentifier])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope =
- SpecificPipelines(orthogonalCandidatePipelines.toSet)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val firstMatchingOrthogonalSourceOpt = orthogonalCandidatePipelines
- .find { orthogonalCandidatePipeline =>
- remainingCandidates.exists(_.source == orthogonalCandidatePipeline)
- }
-
- val remainingCandidatesLimited = firstMatchingOrthogonalSourceOpt match {
- case Some(firstMatchingOrthogonalSource) =>
- val subsequentOrthogonalSources =
- orthogonalCandidatePipelines.toSet - firstMatchingOrthogonalSource
-
- remainingCandidates.filterNot { candidate =>
- subsequentOrthogonalSources.contains(candidate.source)
- }
- case None => remainingCandidates
- }
-
- SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala
deleted file mode 100644
index 47974aff9..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Limit the number of results (for 1 or more modules) from a certain candidate
- * source to PipelineQuery.requestedMaxResults.
- *
- * PipelineQuery.requestedMaxResults is optionally set in the pipelineQuery.
- * If it is not set, then the default value of DefaultRequestedMaxModuleItemsParam is used.
- *
- * For example, if PipelineQuery.requestedMaxResults is 3, and a candidatePipeline returned 1 module
- * containing 10 items in the candidate pool, then these module items will be reduced to the first 3
- * module items. Note that to update the ordering of the candidates, an
- * UpdateModuleItemsCandidateOrderingSelector may be used prior to using this selector.
- *
- * Another example, if PipelineQuery.requestedMaxResults is 3, and a candidatePipeline returned 5
- * modules each containing 10 items in the candidate pool, then the module items in each of the 5
- * modules will be reduced to the first 3 module items.
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class DropRequestedMaxModuleItemCandidates(
- override val pipelineScope: CandidateScope,
- defaultRequestedMaxModuleItemResultsParam: Param[Int])
- extends Selector[PipelineQuery] {
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val requestedMaxModuleItemSelections =
- query.maxResults(defaultRequestedMaxModuleItemResultsParam)
- assert(
- requestedMaxModuleItemSelections > 0,
- "Requested Max module item selections must be greater than zero")
-
- val resultUpdated = result.map {
- case module: ModuleCandidateWithDetails if pipelineScope.contains(module) =>
- // this applies to all candidates in a module, even if they are from a different
- // candidate source which can happen if items are added to a module during selection
- module.copy(candidates =
- DropSelector.takeUntil(requestedMaxModuleItemSelections, module.candidates))
- case candidate => candidate
- }
-
- SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated)
- }
-}
-
-object DropRequestedMaxModuleItemCandidates {
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- defaultRequestedMaxModuleItemResultsParam: Param[Int]
- ) =
- new DropRequestedMaxModuleItemCandidates(
- SpecificPipeline(candidatePipeline),
- defaultRequestedMaxModuleItemResultsParam)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala
deleted file mode 100644
index d5da8f584..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.BoundedParam
-
-/**
- * Limit the number of results to min(PipelineQuery.requestedMaxResults, ServerMaxResultsParam)
- *
- * PipelineQuery.requestedMaxResults is optionally set in the pipelineQuery.
- * If it is not set, then the default value of DefaultRequestedMaxResultsParam is used.
- *
- * ServerMaxResultsParam specifies the maximum number of results supported, irrespective of what is
- * specified by the client in PipelineQuery.requestedMaxResults
- * (or the DefaultRequestedMaxResultsParam default if not specified)
- *
- * For example, if ServerMaxResultsParam is 5, PipelineQuery.requestedMaxResults is 3,
- * and the results contain 10 items, then these items will be reduced to the first 3 selected items.
- *
- * If PipelineQuery.requestedMaxResults is not set, DefaultRequestedMaxResultsParam is 3,
- * ServerMaxResultsParam is 5 and the results contain 10 items,
- * then these items will be reduced to the first 3 selected items.
- *
- * Another example, if ServerMaxResultsParam is 5, PipelineQuery.requestedMaxResults is 8,
- * and the results contain 10 items, then these will be reduced to the first 5 selected items.
- *
- * The items inside the modules will not be affected by this selector.
- */
-case class DropRequestedMaxResults(
- defaultRequestedMaxResultsParam: BoundedParam[Int],
- serverMaxResultsParam: BoundedParam[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = AllPipelines
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val requestedMaxResults = query.maxResults(defaultRequestedMaxResultsParam)
- val serverMaxResults = query.params(serverMaxResultsParam)
- assert(requestedMaxResults > 0, "Requested max results must be greater than zero")
- assert(serverMaxResults > 0, "Server max results must be greater than zero")
-
- val appliedMaxResults = Math.min(requestedMaxResults, serverMaxResults)
- val resultUpdated = DropSelector.takeUntil(appliedMaxResults, result)
-
- SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala
deleted file mode 100644
index b2a1a76e1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import scala.collection.mutable
-
-private[selector] object DropSelector {
-
- /**
- * Identify and merge duplicates using the supplied key extraction and merger functions. By default
- * this will keep only the first instance of a candidate in the `candidate` as determined by comparing
- * the contained candidate ID and class type. Subsequent matching instances will be dropped. For
- * more details, see DropSelector#dropDuplicates.
- *
- * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored.
- * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored.
- *
- * @param candidates which may have elements to drop
- * @param duplicationKey how to generate a key for a candidate for identifying duplicates
- * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one)
- */
- def dropDuplicates[Candidate <: CandidateWithDetails, Key](
- pipelineScope: CandidateScope,
- candidates: Seq[Candidate],
- duplicationKey: DeduplicationKey[Key],
- mergeStrategy: CandidateMergeStrategy
- ): Seq[Candidate] = {
- val seenCandidatePositions = mutable.HashMap[Key, Int]()
- // We assume that, most of the time, most candidates aren't duplicates so the result Seq will be
- // approximately the size of the candidates Seq.
- val deduplicatedCandidates = new mutable.ArrayBuffer[Candidate](candidates.length)
-
- for (candidate <- candidates) {
- candidate match {
-
- // candidate is from one of the Pipelines the selector applies to and is not a CursorCandidate
- case item: ItemCandidateWithDetails
- if pipelineScope.contains(item) &&
- !item.candidate.isInstanceOf[CursorCandidate] =>
- val key = duplicationKey(item)
-
- // Perform a merge if the candidate has been seen already
- if (seenCandidatePositions.contains(key)) {
- val candidateIndex = seenCandidatePositions(key)
-
- // Safe because only ItemCandidateWithDetails are added to seenCandidatePositions so
- // seenCandidatePositions(key) *must* point to an ItemCandidateWithDetails
- val originalCandidate =
- deduplicatedCandidates(candidateIndex).asInstanceOf[ItemCandidateWithDetails]
-
- deduplicatedCandidates.update(
- candidateIndex,
- mergeStrategy(originalCandidate, item).asInstanceOf[Candidate])
- } else {
- // Otherwise add a new entry to the list of kept candidates and update our map to track
- // the new index
- deduplicatedCandidates.append(item.asInstanceOf[Candidate])
- seenCandidatePositions.update(key, deduplicatedCandidates.length - 1)
- }
- case item => deduplicatedCandidates.append(item)
- }
- }
-
- deduplicatedCandidates
- }
-
- /**
- * Takes `candidates` from all [[CandidateWithDetails.source]]s but only `candidates` in the provided
- * `pipelineScope` are counted towards the `max` non-cursor candidates are included.
- *
- * @param max the maximum number of non-cursor candidates from the provided `pipelineScope` to return
- * @param candidates a sequence of candidates which may have elements dropped
- * @param pipelineScope the scope of which `candidates` should count towards the `max`
- */
- def takeUntil[Candidate <: CandidateWithDetails](
- max: Int,
- candidates: Seq[Candidate],
- pipelineScope: CandidateScope = AllPipelines
- ): Seq[Candidate] = {
- val resultsBuilder = Seq.newBuilder[Candidate]
- resultsBuilder.sizeHint(candidates)
-
- candidates.foldLeft(0) {
- case (
- count,
- candidate @ ItemCandidateWithDetails(_: CursorCandidate, _, _)
- ) =>
- // keep cursors, not included in the `count`
- resultsBuilder += candidate.asInstanceOf[Candidate]
- count
-
- case (count, candidate) if !pipelineScope.contains(candidate) =>
- // keep candidates that don't match the provided `pipelineScope`, not included in the `count`
- resultsBuilder += candidate
- count
-
- case (count, candidate) if count < max =>
- // keep candidates if theres space and increment the `count`
- resultsBuilder += candidate
- count + 1
-
- case (dropCurrentCandidate, _) =>
- // drop non-cursor candidate because theres no space left
- dropCurrentCandidate
- }
- resultsBuilder.result()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala
deleted file mode 100644
index ce8be7d6a..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.timelines.configapi.Param
-
-/**
- * Drop all results if the minimum item threshold is not met. Some products would rather return
- * nothing than, for example, a single tweet. This lets us leverage existing client logic for
- * handling no results such as logic to not render the product at all.
- */
-case class DropTooFewResults(minResultsParam: Param[Int]) extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = AllPipelines
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val minResults = query.params(minResultsParam)
- assert(minResults > 0, "Min results must be greater than zero")
-
- if (PipelineResult.resultSize(result) < minResults) {
- SelectorResult(remainingCandidates = remainingCandidates, result = Seq.empty)
- } else {
- SelectorResult(remainingCandidates = remainingCandidates, result = result)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala
deleted file mode 100644
index b0d3326fc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala
+++ /dev/null
@@ -1,124 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-private[selector] object DynamicPositionSelector {
-
- sealed trait IndexType
- case object RelativeIndices extends IndexType
- case object AbsoluteIndices extends IndexType
-
- /**
- * Given an existing `result` seq, inserts candidates from `candidatesToInsertByIndex` into the `result` 1-by-1 with
- * the provided index being the index relative to the `result` if given [[RelativeIndices]] or
- * absolute index if given [[AbsoluteIndices]] (excluding duplicate insertions at an index, see below).
- *
- * Indices below 0 are added to the front and indices > the length are added to the end
- *
- * @note if multiple candidates exist with the same index, they are inserted in the order which they appear and only count
- * as a single element with regards to the absolute index values, see the example below
- *
- * @example when using [[RelativeIndices]] {{{
- * mergeByIndexIntoResult(
- * Seq(
- * 0 -> "a",
- * 0 -> "b",
- * 0 -> "c",
- * 1 -> "e",
- * 2 -> "g",
- * 2 -> "h"),
- * Seq(
- * "D",
- * "F"
- * ),
- * RelativeIndices) == Seq(
- * "a",
- * "b",
- * "c",
- * "D",
- * "e",
- * "F",
- * "g",
- * "h"
- * )
- * }}}
- *
- * @example when using [[AbsoluteIndices]] {{{
- * mergeByIndexIntoResult(
- * Seq(
- * 0 -> "a",
- * 0 -> "b",
- * 1 -> "c",
- * 3 -> "e",
- * 5 -> "g",
- * 6 -> "h"),
- * Seq(
- * "D",
- * "F"
- * ),
- * AbsoluteIndices) == Seq(
- * "a", // index 0, "a" and "b" together only count as 1 element with regards to indexes because they have duplicate insertion points
- * "b", // index 0
- * "c", // index 1
- * "D", // index 2
- * "e", // index 3
- * "F", // index 4
- * "g", // index 5
- * "h" // index 6
- * )
- * }}}
- */
- def mergeByIndexIntoResult[T]( // generic on `T` to simplify unit testing
- candidatesToInsertByIndex: Seq[(Int, T)],
- result: Seq[T],
- indexType: IndexType
- ): Seq[T] = {
- val positionAndCandidateList = candidatesToInsertByIndex.sortWith {
- case ((indexLeft: Int, _), (indexRight: Int, _)) =>
- indexLeft < indexRight // order by desired absolute index ascending
- }
-
- // Merge result and positionAndCandidateList into resultUpdated while making sure that the entries
- // from the positionAndCandidateList are inserted at the right index.
- val resultUpdated = Seq.newBuilder[T]
- resultUpdated.sizeHint(result.size + positionAndCandidateList.size)
-
- var currentResultIndex = 0
- val inputResultIterator = result.iterator
- val positionAndCandidateIterator = positionAndCandidateList.iterator.buffered
- var previousInsertPosition: Option[Int] = None
-
- while (inputResultIterator.nonEmpty && positionAndCandidateIterator.nonEmpty) {
- positionAndCandidateIterator.head match {
- case (nextInsertionPosition, nextCandidateToInsert)
- if previousInsertPosition.contains(nextInsertionPosition) =>
- // inserting multiple candidates at the same index
- resultUpdated += nextCandidateToInsert
- // do not increment any indices, but insert the candidate and advance to the next candidate
- positionAndCandidateIterator.next()
-
- case (nextInsertionPosition, nextCandidateToInsert)
- if currentResultIndex >= nextInsertionPosition =>
- // inserting a candidate at a new index
- // add candidate to the results
- resultUpdated += nextCandidateToInsert
- // save the position of the inserted element to handle duplicate index insertions
- previousInsertPosition = Some(nextInsertionPosition)
- // advance to next candidate
- positionAndCandidateIterator.next()
- if (indexType == AbsoluteIndices) {
- // if the indices are absolute, instead of relative to the original `result` we need to
- // count the insertions of candidates into the results towards the `currentResultIndex`
- currentResultIndex += 1
- }
- case _ =>
- // no candidate to insert by index so use the candidates from the result and increment the index
- resultUpdated += inputResultIterator.next()
- currentResultIndex += 1
- }
- }
- // one of the iterators is empty, so append the remaining candidates in order to the end
- resultUpdated ++= positionAndCandidateIterator.map { case (_, candidate) => candidate }
- resultUpdated ++= inputResultIterator
-
- resultUpdated.result()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala
deleted file mode 100644
index 3096d9a50..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleAndIndex
-import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleWithItemsToAddAndOtherCandidates
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Append all candidates from [[candidatePipeline]] into a module from [[targetModuleCandidatePipeline]].
- * If the results contain multiple modules from the target candidate pipeline,
- * then the candidates will be inserted into the first module.
- *
- * @note this will throw an [[UnsupportedOperationException]] if the [[candidatePipeline]] contains any modules.
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class InsertAppendIntoModuleCandidates(
- candidatePipeline: CandidatePipelineIdentifier,
- targetModuleCandidatePipeline: CandidatePipelineIdentifier)
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope =
- SpecificPipelines(candidatePipeline, targetModuleCandidatePipeline)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val ModuleWithItemsToAddAndOtherCandidates(
- moduleToUpdateAndIndex,
- itemsToInsertIntoModule,
- otherCandidates) =
- InsertIntoModule.moduleToUpdate(
- candidatePipeline,
- targetModuleCandidatePipeline,
- remainingCandidates)
-
- val updatedRemainingCandidates = moduleToUpdateAndIndex match {
- case None => remainingCandidates
- case _ if itemsToInsertIntoModule.isEmpty => remainingCandidates
- case Some(ModuleAndIndex(moduleToUpdate, indexOfModuleInOtherCandidates)) =>
- val updatedModuleItems = moduleToUpdate.candidates ++ itemsToInsertIntoModule
- val updatedModule = moduleToUpdate.copy(candidates = updatedModuleItems)
- otherCandidates.updated(indexOfModuleInOtherCandidates, updatedModule)
- }
-
- SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala
deleted file mode 100644
index 79dda59f4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import scala.collection.mutable
-
-/**
- * Select candidates and add them according to the `pattern`.
- * The pattern is repeated until all candidates contained in the pattern are added to the `result`.
- * If the candidates for a specific [[Bucket]] in the pattern are exhausted, that [[Bucket]] will be
- * skipped on subsequent iterations.
- * If a candidate has a [[Bucket]] that isn't in the pattern it is added to the end of the `result`.
- * The end result is all candidates from all [[candidatePipelines]]s provided will end up in the result.
- *
- * @example If there are no more candidates from a given `CandidatePipeline` then it is skipped, so
- * with the pattern `Seq(A, A, B, C)`, if there are no more candidates from `B` then it is
- * effectively the same as `Seq(A, A, C)`. The `result` will contain all candidates from all
- * `CandidatePipeline`s who's `Bucket` is in the `pattern`.
- *
- * @example If the pattern is `Seq(A, A, B, C)` and the remaining candidates
- * from the provided `candidatePipelines` are:
- * - 5 `A`s
- * - 2 `B`s
- * - 1 `C`
- * - 1 `D`s
- *
- * then the resulting output for each iteration over the pattern is
- * - `Seq(A, A, B, C)`
- * - `Seq(A, A, B)` since there's no more `C`s
- * - `Seq(A)` since there are no more `B`s or `C`s
- * - `Seq(D)` since it wasn't in the pattern but is from one of the provided
- * `candidatePipelines`, it's appended at the end
- *
- * so the `result` that's returned would be `Seq(A, A, B, C, A, A, B, A, D)`
- */
-case class InsertAppendPatternResults[-Query <: PipelineQuery, Bucket](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- bucketer: Bucketer[Bucket],
- pattern: Seq[Bucket])
- extends Selector[Query] {
-
- require(pattern.nonEmpty, "`pattern` must be non-empty")
-
- override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipelines)
-
- private sealed trait PatternResult
- private case object NotASelectedCandidatePipeline extends PatternResult
- private case object NotABucketInThePattern extends PatternResult
- private case class Bucketed(bucket: Bucket) extends PatternResult
-
- private val allBucketsInPattern = pattern.toSet
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val groupedCandidates: Map[PatternResult, Seq[CandidateWithDetails]] =
- remainingCandidates.groupBy { candidateWithDetails =>
- if (pipelineScope.contains(candidateWithDetails)) {
- // if a candidate's Bucket doesnt appear in the pattern it's backfilled at the end
- val bucket = bucketer(candidateWithDetails)
- if (allBucketsInPattern.contains(bucket)) {
- Bucketed(bucket)
- } else {
- NotABucketInThePattern
- }
- } else {
- NotASelectedCandidatePipeline
- }
- }
-
- val otherCandidates =
- groupedCandidates.getOrElse(NotASelectedCandidatePipeline, Seq.empty)
-
- val notABucketInThePattern =
- groupedCandidates.getOrElse(NotABucketInThePattern, Seq.empty)
-
- // mutable so we can remove finished iterators to optimize when looping for large patterns
- val groupedBucketsIterators = mutable.HashMap(groupedCandidates.collect {
- case (Bucketed(bucket), candidatesWithDetails) => (bucket, candidatesWithDetails.iterator)
- }.toSeq: _*)
-
- val patternIterator = Iterator.continually(pattern).flatten
-
- val newResult = new mutable.ArrayBuffer[CandidateWithDetails]()
- while (groupedBucketsIterators.nonEmpty) {
- val bucket = patternIterator.next()
- groupedBucketsIterators.get(bucket) match {
- case Some(iterator) if iterator.nonEmpty => newResult += iterator.next()
- case Some(_) => groupedBucketsIterators.remove(bucket)
- case None =>
- }
- }
-
- SelectorResult(
- remainingCandidates = otherCandidates,
- result = result ++ newResult ++ notABucketInThePattern)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala
deleted file mode 100644
index f60b0abbc..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala
+++ /dev/null
@@ -1,171 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-import scala.annotation.tailrec
-import scala.collection.mutable
-import scala.util.Random
-
-/**
- * Select candidates and add them according to the ratio assigned for each [[Bucket]]
- * For instance, if given `Set((A, 0.8), (B, 0.2))` then candidates will randomly be added to the
- * results with an 80% chance of any candidate being from `A` and 20% from`B`. If there are no more
- * candidates from a given `CandidatePipeline` then it's simply skipped, so if we run out of `A`
- * candidates the rest will be `B`. The end result is all candidates from all [[candidatePipelines]]s
- * provided will end up in the result.
- *
- * For example, an output may look like `Seq(A, A, B, A, A)`, `Seq(A, A, A, A, B)`. If we eventually
- * run out of `A` candidates then we would end up with the remaining candidates at the end,
- * `Seq(A, A, B, A, A, A, B, A, A, A [run out of A], B, B, B, B, B, B)`
- *
- * @note the ratios provided are proportional to the sum of all ratios, so if you give 0.3 and 0.7,
- * they will be function as to 30% and 70%, and the same for if you provided 3000 and 7000 for
- * ratios.
- *
- * @note Its important to be sure to update all [[Param]]s when changing the ratio for 1 of them
- * otherwise you may get unexpected results. For instance, of you have 0.3 and 0.7 which
- * correspond to 30% and 70%, and you change `0.7 -> 0.9`, then the total sum of the ratios is
- * now 1.2, so you have 25% and 75% when you intended to have 10% and 90%. To prevent this,
- * be sure to update all [[Param]]s together, so `0.3 -> 0.1` and `0.7 -> 0.9` so the total
- * remains the same.
- */
-case class InsertAppendRatioResults[-Query <: PipelineQuery, Bucket](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- bucketer: Bucketer[Bucket],
- ratios: Map[Bucket, Param[Double]],
- random: Random = new Random(0))
- extends Selector[Query] {
-
- require(ratios.nonEmpty, "bucketRatios must be non-empty")
-
- override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipelines)
-
- private sealed trait PatternResult
- private case object NotASelectedCandidatePipeline extends PatternResult
- private case object NotABucketInThePattern extends PatternResult
- private case class Bucketed(bucket: Bucket) extends PatternResult
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val groupedCandidates: Map[PatternResult, Seq[CandidateWithDetails]] =
- remainingCandidates.groupBy { candidateWithDetails =>
- if (pipelineScope.contains(candidateWithDetails)) {
- // if a candidate's Bucket doesnt appear in the pattern it's backfilled at the end
- val bucket = bucketer(candidateWithDetails)
- if (ratios.contains(bucket)) {
- Bucketed(bucket)
- } else {
- NotABucketInThePattern
- }
- } else {
- NotASelectedCandidatePipeline
- }
- }
-
- val otherCandidates =
- groupedCandidates.getOrElse(NotASelectedCandidatePipeline, Seq.empty)
-
- val notABucketInThePattern =
- groupedCandidates.getOrElse(NotABucketInThePattern, Seq.empty)
-
- val groupedCandidatesIterators = groupedCandidates.collect {
- case (Bucketed(bucket), candidatesWithDetails) => (bucket, candidatesWithDetails.iterator)
- }
-
- // using a LinkedHashMap and sorting by descending ratio
- // the highest ratios will always be checked first when iterating
- // mutable so we can remove finished ratios when they are finished to optimize looping for large numbers of ratios
- val currentBucketRatios: mutable.Map[Bucket, Double] = {
- val bucketsAndRatiosSortedByRatio =
- ratios.iterator
- .map {
- case (bucket, param) =>
- val ratio = query.params(param)
- require(
- ratio >= 0,
- "The ratio for an InsertAppendRatioResults selector can not be negative")
- (bucket, ratio)
- }.toSeq
- .sortBy { case (_, ratio) => ratio }(Ordering.Double.reverse)
- mutable.LinkedHashMap(bucketsAndRatiosSortedByRatio: _*)
- }
-
- // keep track of the sum of all ratios so we can look only at random values between 0 and that
- var ratioSum = currentBucketRatios.valuesIterator.sum
-
- // add candidates to `newResults` until all remaining candidates are for a single bucket
- val newResult = new mutable.ArrayBuffer[CandidateWithDetails]()
- while (currentBucketRatios.size > 1) {
- // random number between 0 and the sum of the ratios of all params
- val randomValue = random.nextDouble() * ratioSum
-
- val currentBucketRatiosIterator: Iterator[(Bucket, Double)] =
- currentBucketRatios.iterator
- val (currentBucket, ratio) = currentBucketRatiosIterator.next()
-
- val componentToTakeFrom = findBucketToTakeFrom(
- randomValue = randomValue,
- cumulativeSumOfRatios = ratio,
- bucket = currentBucket,
- bucketRatiosIterator = currentBucketRatiosIterator
- )
-
- groupedCandidatesIterators.get(componentToTakeFrom) match {
- case Some(iteratorForBucket) if iteratorForBucket.nonEmpty =>
- newResult += iteratorForBucket.next()
- case _ =>
- ratioSum -= currentBucketRatios(componentToTakeFrom)
- currentBucketRatios.remove(componentToTakeFrom)
- }
- }
- // with only have 1 source remaining, we can skip all the above work and insert them in bulk
- val remainingBucketInRatio =
- currentBucketRatios.keysIterator.flatMap(groupedCandidatesIterators.get).flatten
-
- SelectorResult(
- remainingCandidates = otherCandidates,
- result = result ++ newResult ++ remainingBucketInRatio ++ notABucketInThePattern)
- }
-
- /**
- * iterates through the `bucketRatiosIterator` until it finds a the
- * [[Bucket]] that corresponds with the current `randomValue`.
- *
- * This method expects that `0 <= randomValue <= sum of all ratios`
- *
- * @example If the given ratios are `Seq(A -> 0.2, B -> 0.35, C -> 0.45)`
- * check if the given `randomValue` is
- * - `< 0.45`, if not then check
- * - `< 0.8` (0.45 + 0.35), if not then check
- * - `< 1.0` (0.45 + 0.35 + 0.2)
- *
- * and return the corresponding [[Bucket]]
- */
- @tailrec private def findBucketToTakeFrom(
- randomValue: Double,
- cumulativeSumOfRatios: Double,
- bucket: Bucket,
- bucketRatiosIterator: Iterator[(Bucket, Double)]
- ): Bucket = {
- if (randomValue < cumulativeSumOfRatios || bucketRatiosIterator.isEmpty) {
- bucket
- } else {
- val (nextBucket, ratio) = bucketRatiosIterator.next()
- findBucketToTakeFrom(
- randomValue,
- cumulativeSumOfRatios + ratio,
- nextBucket,
- bucketRatiosIterator)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala
deleted file mode 100644
index a3e8485c3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object InsertAppendResults {
- def apply(candidatePipeline: CandidatePipelineIdentifier): InsertAppendResults[PipelineQuery] =
- new InsertAppendResults(SpecificPipeline(candidatePipeline))
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier]
- ): InsertAppendResults[PipelineQuery] = new InsertAppendResults(
- SpecificPipelines(candidatePipelines))
-}
-
-/**
- * Select all candidates from candidate pipeline(s) and append to the end of the result.
- *
- * @note that if multiple candidate pipelines are specified, their candidates will be added
- * to the result in the order in which they appear in the candidate pool. This ordering often
- * reflects the order in which the candidate pipelines were listed in the mixer/recommendations
- * pipeline, unless for example an UpdateSortCandidates selector was run prior to running
- * this selector which could change this ordering.
- *
- * @note if inserting results from multiple candidate pipelines (see note above related to ordering),
- * it is more performant to include all (or a subset) of the candidate pipelines in a single
- * InsertAppendResults, as opposed to calling InsertAppendResults individually for each
- * candidate pipeline because each selector does an O(n) pass on the candidate pool.
- */
-case class InsertAppendResults[-Query <: PipelineQuery](
- override val pipelineScope: CandidateScope)
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val PartitionedCandidates(selectedCandidates, otherCandidates) =
- pipelineScope.partition(remainingCandidates)
-
- val resultUpdated = result ++ selectedCandidates
-
- SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala
deleted file mode 100644
index 73ba481b5..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import scala.collection.mutable
-
-object InsertAppendWeaveResults {
- def apply[Query <: PipelineQuery, Bucket](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- bucketer: Bucketer[Bucket],
- ): InsertAppendWeaveResults[Query, Bucket] =
- new InsertAppendWeaveResults(SpecificPipelines(candidatePipelines), bucketer)
-
- def apply[Query <: PipelineQuery, Bucket](
- candidatePipeline: CandidatePipelineIdentifier,
- bucketer: Bucketer[Bucket],
- ): InsertAppendWeaveResults[Query, Bucket] =
- new InsertAppendWeaveResults(SpecificPipeline(candidatePipeline), bucketer)
-}
-
-/**
- * Select candidates weave them together according to their [[Bucket]].
- *
- * Candidates are grouped according to [[Bucket]] and one candidate is added from each group until
- * no candidates belonging to any group are left.
- *
- * Functionally similar to [[InsertAppendPatternResults]]. [[InsertAppendPatternResults]] is useful
- * if you have more complex ordering requirements but it requires you to know all the buckets in
- * advance.
- *
- * @note The order in which candidates are weaved together depends on the order in which the buckets
- * were first seen on candidates.
- *
- * @example If the candidates are Seq(Tweet(10), Tweet(8), Tweet(3), Tweet(13)) and they are bucketed
- * using an IsEven bucketing function, then the resulting buckets would be:
- *
- * - Seq(Tweet(10), Tweet(8))
- * - Seq(Tweet(3), Tweet(13))
- *
- * The selector would then loop through these buckets and produce:
- *
- * - Tweet(10)
- * - Tweet(3)
- * - Tweet(8)
- * - Tweet(13)
- *
- * Note that first bucket encountered was the 'even' bucket so weaving proceeds first with
- * the even bucket then the odd bucket. Tweet(3) had been first then the opposite would be
- * true.
- */
-case class InsertAppendWeaveResults[-Query <: PipelineQuery, Bucket](
- override val pipelineScope: CandidateScope,
- bucketer: Bucketer[Bucket])
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val (bucketableCandidates, otherCandidates) =
- remainingCandidates.partition(pipelineScope.contains)
-
- val groupedCandidates = groupByBucket(bucketableCandidates)
-
- val candidateBucketQueues: mutable.Queue[mutable.Queue[CandidateWithDetails]] =
- mutable.Queue() ++= groupedCandidates
- val newResult = mutable.ArrayBuffer[CandidateWithDetails]()
-
- // Take the next group of candidates from the queue and attempt to add the first candidate from
- // that group into the result. The loop will terminate when every queue is empty.
- while (candidateBucketQueues.nonEmpty) {
- val nextCandidateQueue = candidateBucketQueues.dequeue()
-
- if (nextCandidateQueue.nonEmpty) {
- newResult += nextCandidateQueue.dequeue()
-
- // Re-queue this bucket of candidates if it's still non-empty
- if (nextCandidateQueue.nonEmpty) {
- candidateBucketQueues.enqueue(nextCandidateQueue)
- }
- }
- }
-
- SelectorResult(remainingCandidates = otherCandidates, result = result ++ newResult)
- }
-
- /**
- * Similar to `groupBy` but respect the order in which individual bucket values are first seen.
- * This is useful when the candidates have already been sorted prior to the selector running.
- */
- private def groupByBucket(
- candidates: Seq[CandidateWithDetails]
- ): mutable.ArrayBuffer[mutable.Queue[CandidateWithDetails]] = {
- val bucketToCandidateGroupIndex = mutable.Map.empty[Bucket, Int]
- val candidateGroups = mutable.ArrayBuffer[mutable.Queue[CandidateWithDetails]]()
-
- candidates.foreach { candidate =>
- val bucket = bucketer(candidate)
-
- // Index points to the specific sub-group in candidateGroups where we want to insert the next
- // candidate. If a bucket has already been seen then this value is known, otherwise we need
- // to add a new entry for it.
- if (!bucketToCandidateGroupIndex.contains(bucket)) {
- candidateGroups.append(mutable.Queue())
- bucketToCandidateGroupIndex.put(bucket, candidateGroups.length - 1)
- }
-
- candidateGroups(bucketToCandidateGroupIndex(bucket)).enqueue(candidate)
- }
-
- candidateGroups
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala
deleted file mode 100644
index 26767ffb7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * A selector that appends all candidates missing a specific feature to the results pool and keeps
- * the rest in the remaining candidates. This is useful for backfill scoring candidates without
- * a score from a previous scorer.
- * @param pipelineScope The pipeline scope to check
- * @param missingFeature The missing feature to check for.
- */
-case class InsertAppendWithoutFeatureResults(
- override val pipelineScope: CandidateScope,
- missingFeature: Feature[_, _])
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val (candidatesWithMissingFeature, candidatesWithFeature) = remainingCandidates.partition {
- candidate =>
- pipelineScope.contains(candidate) && !candidate.features.getSuccessfulFeatures
- .contains(missingFeature)
- }
- val updatedResults = result ++ candidatesWithMissingFeature
- SelectorResult(remainingCandidates = candidatesWithFeature, result = updatedResults)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala
deleted file mode 100644
index e0fb9bebb..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector._
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object InsertDynamicPositionResults {
- def apply[Query <: PipelineQuery](
- candidatePipeline: CandidatePipelineIdentifier,
- dynamicInsertionPosition: DynamicInsertionPosition[Query],
- ): InsertDynamicPositionResults[Query] =
- new InsertDynamicPositionResults(SpecificPipeline(candidatePipeline), dynamicInsertionPosition)
-
- def apply[Query <: PipelineQuery](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- dynamicInsertionPosition: DynamicInsertionPosition[Query]
- ): InsertDynamicPositionResults[Query] =
- new InsertDynamicPositionResults(
- SpecificPipelines(candidatePipelines),
- dynamicInsertionPosition)
-}
-
-/**
- * Compute a position for inserting the candidates into result. If a `None` is returned, the
- * Selector using this would not insert the candidates into the result.
- */
-trait DynamicInsertionPosition[-Query <: PipelineQuery] {
- def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Option[Int]
-}
-
-/**
- * Insert all candidates in a pipeline scope at a 0-indexed dynamic position computed
- * using the provided [[DynamicInsertionPosition]] instance. If the current results are a shorter
- * length than the computed position, then the candidates will be appended to the results.
- * If the [[DynamicInsertionPosition]] returns a `None`, the candidates are not
- * added to the result.
- */
-case class InsertDynamicPositionResults[-Query <: PipelineQuery](
- override val pipelineScope: CandidateScope,
- dynamicInsertionPosition: DynamicInsertionPosition[Query])
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- dynamicInsertionPosition(query, remainingCandidates, result) match {
- case Some(position) =>
- InsertSelector.insertIntoResultsAtPosition(
- position = position,
- pipelineScope = pipelineScope,
- remainingCandidates = remainingCandidates,
- result = result)
- case None =>
- // When a valid position is not provided, do not insert the candidates.
- // Both the remainingCandidates and result are unchanged.
- SelectorResult(remainingCandidates = remainingCandidates, result = result)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala
deleted file mode 100644
index 1fb4d61be..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleAndIndex
-import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleWithItemsToAddAndOtherCandidates
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Insert all candidates from [[candidatePipeline]] at a 0-indexed fixed position into a module from
- * [[targetModuleCandidatePipeline]]. If the results contain multiple modules from the target candidate
- * pipeline, then the candidates will be inserted into the first module. If the target module's
- * items are a shorter length than the requested position, then the candidates will be appended
- * to the results.
- *
- * @note this will throw an [[UnsupportedOperationException]] if the [[candidatePipeline]] contains any modules.
- *
- * @note this updates the module in the `remainingCandidates`
- */
-case class InsertFixedPositionIntoModuleCandidates(
- candidatePipeline: CandidatePipelineIdentifier,
- targetModuleCandidatePipeline: CandidatePipelineIdentifier,
- positionParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope =
- SpecificPipelines(candidatePipeline, targetModuleCandidatePipeline)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val position = query.params(positionParam)
- assert(position >= 0, "Position must be equal to or greater than zero")
-
- val ModuleWithItemsToAddAndOtherCandidates(
- moduleToUpdateAndIndex,
- itemsToInsertIntoModule,
- otherCandidates) =
- InsertIntoModule.moduleToUpdate(
- candidatePipeline,
- targetModuleCandidatePipeline,
- remainingCandidates)
-
- val updatedRemainingCandidates = moduleToUpdateAndIndex match {
- case None => remainingCandidates
- case _ if itemsToInsertIntoModule.isEmpty => remainingCandidates
- case Some(ModuleAndIndex(moduleToUpdate, indexOfModuleInOtherCandidates)) =>
- val updatedModuleItems =
- if (position < moduleToUpdate.candidates.length) {
- val (left, right) = moduleToUpdate.candidates.splitAt(position)
- left ++ itemsToInsertIntoModule ++ right
- } else {
- moduleToUpdate.candidates ++ itemsToInsertIntoModule
- }
- val updatedModule = moduleToUpdate.copy(candidates = updatedModuleItems)
- otherCandidates.updated(indexOfModuleInOtherCandidates, updatedModule)
- }
-
- SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala
deleted file mode 100644
index ef2f392a1..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-object InsertFixedPositionResults {
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- positionParam: Param[Int],
- ): InsertFixedPositionResults =
- new InsertFixedPositionResults(SpecificPipeline(candidatePipeline), positionParam)
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier],
- positionParam: Param[Int]
- ): InsertFixedPositionResults =
- new InsertFixedPositionResults(SpecificPipelines(candidatePipelines), positionParam)
-}
-
-/**
- * Insert all candidates in a pipeline scope at a 0-indexed fixed position. If the current
- * results are a shorter length than the requested position, then the candidates will be appended
- * to the results.
- */
-case class InsertFixedPositionResults(
- override val pipelineScope: CandidateScope,
- positionParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = InsertSelector.insertIntoResultsAtPosition(
- position = query.params(positionParam),
- pipelineScope = pipelineScope,
- remainingCandidates = remainingCandidates,
- result = result)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala
deleted file mode 100644
index 53f3df75f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import scala.collection.immutable.Queue
-
-private[selector] object InsertIntoModule {
- case class ModuleAndIndex(
- moduleToInsertInto: ModuleCandidateWithDetails,
- indexOfModuleInOtherCandidates: Int)
-
- case class ModuleWithItemsToAddAndOtherCandidates(
- moduleToUpdateAndIndex: Option[ModuleAndIndex],
- itemsToInsertIntoModule: Queue[ItemCandidateWithDetails],
- otherCandidates: Queue[CandidateWithDetails])
-
- /**
- * Given a Seq of `candidates`, returns the first module with it's index that matches the
- * `targetModuleCandidatePipeline` with all the [[ItemCandidateWithDetails]] that match the
- * `candidatePipeline` added to the `itemsToInsert` and the remaining candidates, including the
- * module, in the `otherCandidates`
- */
- def moduleToUpdate(
- candidatePipeline: CandidatePipelineIdentifier,
- targetModuleCandidatePipeline: CandidatePipelineIdentifier,
- candidates: Seq[CandidateWithDetails]
- ): ModuleWithItemsToAddAndOtherCandidates = {
- candidates.foldLeft[ModuleWithItemsToAddAndOtherCandidates](
- ModuleWithItemsToAddAndOtherCandidates(None, Queue.empty, Queue.empty)) {
- case (
- state @ ModuleWithItemsToAddAndOtherCandidates(_, itemsToInsertIntoModule, _),
- selectedItem: ItemCandidateWithDetails) if selectedItem.source == candidatePipeline =>
- state.copy(itemsToInsertIntoModule = itemsToInsertIntoModule :+ selectedItem)
-
- case (
- state @ ModuleWithItemsToAddAndOtherCandidates(None, _, otherCandidates),
- module: ModuleCandidateWithDetails) if module.source == targetModuleCandidatePipeline =>
- val insertionIndex = otherCandidates.length
- val moduleAndIndex = Some(
- ModuleAndIndex(
- moduleToInsertInto = module,
- indexOfModuleInOtherCandidates = insertionIndex))
- val otherCandidatesWithModuleAppended = otherCandidates :+ module
- state.copy(
- moduleToUpdateAndIndex = moduleAndIndex,
- otherCandidates = otherCandidatesWithModuleAppended)
-
- case (_, invalidModule: ModuleCandidateWithDetails)
- if invalidModule.source == candidatePipeline =>
- /**
- * while not exactly an illegal state, its most likely an incorrectly configured candidate pipeline
- * that returned a module instead of returning the candidates the module contains. Since you can't
- * nest a module inside of a module, we can either throw or ignore it and we choose to ignore it
- * to catch a potential bug a customer may do accidentally.
- */
- throw new UnsupportedOperationException(
- s"Expected the candidatePipeline $candidatePipeline to contain items to put into the module from the targetModuleCandidatePipeline $targetModuleCandidatePipeline, but not contain modules itself. " +
- s"This can occur if your $candidatePipeline was incorrectly configured and returns a module when you intended to return the candidates the module contained."
- )
-
- case (
- state @ ModuleWithItemsToAddAndOtherCandidates(_, _, otherCandidates),
- unselectedCandidate) =>
- state.copy(otherCandidates = otherCandidates :+ unselectedCandidate)
- }
- }
-
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala
deleted file mode 100644
index 5c923ad9c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object InsertPerCandidateDynamicPositionResults {
- def apply[Query <: PipelineQuery](
- candidatePipeline: CandidatePipelineIdentifier,
- candidatePositionInResults: CandidatePositionInResults[Query]
- ): InsertPerCandidateDynamicPositionResults[Query] =
- InsertPerCandidateDynamicPositionResults[Query](
- SpecificPipeline(candidatePipeline),
- candidatePositionInResults)
-
- def apply[Query <: PipelineQuery](
- candidatePipelines: Set[CandidatePipelineIdentifier],
- candidatePositionInResults: CandidatePositionInResults[Query]
- ): InsertPerCandidateDynamicPositionResults[Query] =
- InsertPerCandidateDynamicPositionResults[Query](
- SpecificPipelines(candidatePipelines),
- candidatePositionInResults)
-}
-
-/**
- * Insert each candidate in the [[CandidateScope]] at the index relative to the original candidate in the `result`
- * at that index using the provided [[CandidatePositionInResults]] instance. If the current results are shorter
- * length than the computed position, then the candidate will be appended to the results.
- *
- * When the [[CandidatePositionInResults]] returns a `None`, that candidate is not
- * added to the result. Negative position values are treated as 0 (front of the results).
- *
- * @example if [[CandidatePositionInResults]] results in a candidate mapping from index to candidate of
- * `{0 -> a, 0 -> b, 0 -> c, 1 -> e, 2 -> g, 2 -> h} ` with original `results` = `[D, F]`,
- * then the resulting output would look like `[a, b, c, D, e, F, g, h]`
- */
-case class InsertPerCandidateDynamicPositionResults[-Query <: PipelineQuery](
- pipelineScope: CandidateScope,
- candidatePositionInResults: CandidatePositionInResults[Query])
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val (candidatesToInsert, otherRemainingCandidatesTuples) = remainingCandidates
- .map { candidate: CandidateWithDetails =>
- val position =
- if (pipelineScope.contains(candidate))
- candidatePositionInResults(query, candidate, result)
- else
- None
- (position, candidate)
- }.partition { case (index, _) => index.isDefined }
-
- val otherRemainingCandidates = otherRemainingCandidatesTuples.map {
- case (_, candidate) => candidate
- }
-
- val positionAndCandidateList = candidatesToInsert.collect {
- case (Some(position), candidate) => (position, candidate)
- }
-
- val mergedResult = DynamicPositionSelector.mergeByIndexIntoResult(
- positionAndCandidateList,
- result,
- DynamicPositionSelector.RelativeIndices
- )
-
- SelectorResult(remainingCandidates = otherRemainingCandidates, result = mergedResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala
deleted file mode 100644
index a6f4feae8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.InsertRandomPositionResults.randomIndices
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.configapi.StaticParam
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-import scala.collection.mutable
-import scala.util.Random
-
-object InsertRandomPositionResults {
-
- /**
- * Iterator containing random index between `startIndex` and `endIndex` + `n`
- * where `n` is the number of times `next` has been called on the iterator
- * without duplication
- */
- private[selector] def randomIndices(
- resultLength: Int,
- startIndex: Int,
- endIndex: Int,
- random: Random
- ): Iterator[Int] = {
-
- /** exclusive because [[Random.nextInt]]'s bound is exclusive */
- val indexUpperBound = Math.min(endIndex, resultLength)
-
- /**
- * keep track of the available indices, `O(n)` space where `n` is `min(endIndex, resultLength) - max(startIndex, 0)`
- * this ensures fairness which duplicate indices could otherwise skew
- */
- val values = mutable.ArrayBuffer(Math.max(0, startIndex) to indexUpperBound: _*)
-
- /**
- * Iterator that starts at 1 above the last valid index, [[indexUpperBound]] + 1, and increments monotonically
- * representing the new highest index possible in the results for the next call
- */
- Iterator
- .from(indexUpperBound + 1)
- .map { indexUpperBound =>
- /**
- * pick a random index-to-insert-candidate-into-results from [[values]] replacing the value at
- * the chosen index with the new highest index from [[indexUpperBound]], this results in
- * constant time for picking the random index and adding the new highest valid index instead
- * of removing the item from the middle and appending the new, which would be `O(n)` to shift
- * all indices after the removal point
- */
- val i = random.nextInt(values.length)
- val randomIndexToUse = values(i)
- // override the value at i with the new `upperBoundExclusive` to account for the new index value in the next iteration
- values(i) = indexUpperBound
-
- randomIndexToUse
- }
- }
-}
-
-sealed trait InsertedCandidateOrder
-
-/**
- * Candidates from the `remainingCandidates` side will be inserted in a random order into the `result`
- *
- * @example if inserting `[ x, y, z ]` into the `result` then the relative positions of `x`, `y` and `z`
- * to each other is random, e.g. `y` could come before `x` in the result.
- */
-case object UnstableOrderingOfInsertedCandidates extends InsertedCandidateOrder
-
-/**
- * Candidates from the `remainingCandidates` side will be inserted in their original order into the `result`
- *
- * @example if inserting `[ x, y, z ]` into the `result` then the relative positions of `x`, `y` and `z`
- * to each other will remain the same, e.g. `x` is always before `y` is always before `z` in the final result
- */
-case object StableOrderingOfInsertedCandidates extends InsertedCandidateOrder
-
-/**
- * Insert `remainingCandidates` into a random position between the specified indices (inclusive)
- *
- * @example let `result` = `[ a, b, c, d ]` and we want to insert randomly `[ x, y, z ]`
- * with `startIndex` = 1, `endIndex` = 2, and [[UnstableOrderingOfInsertedCandidates]].
- * We can expect a result that looks like `[ a, ... , d ]` where `...` is
- * a random insertion of `x`, `y`, and `z` into `[ b, c ]`. So this could look like
- * `[ a, y, b, x, c, z, d ]`, note that the inserted elements are randomly distributed
- * among the elements that were originally between the specified indices.
- * This functions like taking a slice of the original `result` between the indices,
- * e.g. `[ b, c ]`, then randomly inserting into the slice, e.g. `[ y, b, x, c, z ]`,
- * before reassembling the `result`, e.g. `[ a ] ++ [ y, b, x, c, z ] ++ [ d ]`.
- *
- * @example let `result` = `[ a, b, c, d ]` and we want to insert randomly `[ x, y, z ]`
- * with `startIndex` = 1, `endIndex` = 2, and [[StableOrderingOfInsertedCandidates]].
- * We can expect a result that looks something like `[ a, x, b, y, c, z, d ]`,
- * where `x` is before `y` which is before `z`
- *
- * @param startIndex an inclusive index which starts the range where the candidates will be inserted
- * @param endIndex an inclusive index which ends the range where the candidates will be inserted
- */
-case class InsertRandomPositionResults[-Query <: PipelineQuery](
- pipelineScope: CandidateScope,
- remainingCandidateOrder: InsertedCandidateOrder,
- startIndex: Param[Int] = StaticParam(0),
- endIndex: Param[Int] = StaticParam(Int.MaxValue),
- random: Random = new Random(0))
- extends Selector[Query] {
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val PartitionedCandidates(candidatesInScope, candidatesOutOfScope) =
- pipelineScope.partition(remainingCandidates)
-
- val randomIndexIterator = {
- val randomIndexIterator =
- randomIndices(result.length, query.params(startIndex), query.params(endIndex), random)
-
- remainingCandidateOrder match {
- case StableOrderingOfInsertedCandidates =>
- randomIndexIterator.take(candidatesInScope.length).toSeq.sorted.iterator
- case UnstableOrderingOfInsertedCandidates =>
- randomIndexIterator
- }
- }
-
- val mergedResult = DynamicPositionSelector.mergeByIndexIntoResult(
- candidatesToInsertByIndex = randomIndexIterator.zip(candidatesInScope.iterator).toSeq,
- result = result,
- DynamicPositionSelector.AbsoluteIndices
- )
-
- SelectorResult(remainingCandidates = candidatesOutOfScope, result = mergedResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala
deleted file mode 100644
index e3212c58b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-/**
- * Insert all candidates from a candidate pipeline at a position below, relative to the last
- * selection of the relative to candidate pipeline. If the relative to candidate pipeline does not
- * contain candidates, then the candidates will be inserted with padding relative to position zero.
- * If the current results are a shorter length than the requested padding, then the candidates will
- * be appended to the results.
- */
-case class InsertRelativePositionResults(
- candidatePipeline: CandidatePipelineIdentifier,
- relativeToCandidatePipeline: CandidatePipelineIdentifier,
- paddingAboveParam: Param[Int])
- extends Selector[PipelineQuery] {
-
- override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline)
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val paddingAbove = query.params(paddingAboveParam)
- assert(paddingAbove >= 0, "Padding above must be equal to or greater than zero")
-
- val PartitionedCandidates(selectedCandidates, otherCandidates) =
- pipelineScope.partition(remainingCandidates)
-
- val resultUpdated = if (selectedCandidates.nonEmpty) {
- // If the relativeToCandidatePipeline has zero candidates, lastIndexWhere will return -1 which
- // will start padding from the zero position
- val relativePosition = result.lastIndexWhere(_.source == relativeToCandidatePipeline) + 1
- val position = relativePosition + paddingAbove
-
- if (position < result.length) {
- val (left, right) = result.splitAt(position)
- left ++ selectedCandidates ++ right
- } else {
- result ++ selectedCandidates
- }
- } else {
- result
- }
-
- SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala
deleted file mode 100644
index dd814bf72..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-private[selector] object InsertSelector {
-
- /**
- * Insert all candidates from a candidate pipeline at a 0-indexed fixed position. If the current
- * results are a shorter length than the requested position, then the candidates will be appended
- * to the results.
- */
- def insertIntoResultsAtPosition(
- position: Int,
- pipelineScope: CandidateScope,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- assert(position >= 0, "Position must be equal to or greater than zero")
-
- val PartitionedCandidates(selectedCandidates, otherCandidates) =
- pipelineScope.partition(remainingCandidates)
-
- val resultUpdated = if (selectedCandidates.nonEmpty) {
- if (position < result.length) {
- val (left, right) = result.splitAt(position)
- left ++ selectedCandidates ++ right
- } else {
- result ++ selectedCandidates
- }
- } else {
- result
- }
-
- SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala
deleted file mode 100644
index f4e8bb515..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.timelines.configapi.Param
-
-trait IncludeSelector[-Query <: PipelineQuery] {
- def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Boolean
-}
-
-/**
- * Run [[selector]] if [[includeSelector]] resolves to true, else no-op the selector
- */
-case class SelectConditionally[-Query <: PipelineQuery](
- selector: Selector[Query],
- includeSelector: IncludeSelector[Query])
- extends Selector[Query] {
-
- override val pipelineScope: CandidateScope = selector.pipelineScope
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- if (includeSelector(query, remainingCandidates, result)) {
- selector(query, remainingCandidates, result)
- } else SelectorResult(remainingCandidates = remainingCandidates, result = result)
- }
-}
-
-object SelectConditionally {
-
- /**
- * Wrap each [[Selector]] in `selectors` in an [[IncludeSelector]] with `includeSelector` as the [[SelectConditionally.includeSelector]]
- */
- def apply[Query <: PipelineQuery](
- selectors: Seq[Selector[Query]],
- includeSelector: IncludeSelector[Query]
- ): Seq[Selector[Query]] =
- selectors.map(SelectConditionally(_, includeSelector))
-
- /**
- * A [[SelectConditionally]] based on a [[Param]]
- */
- def paramGated[Query <: PipelineQuery](
- selector: Selector[Query],
- enabledParam: Param[Boolean],
- ): SelectConditionally[Query] =
- SelectConditionally(selector, (query, _, _) => query.params(enabledParam))
-
- /**
- * Wrap each [[Selector]] in `selectors` in a [[SelectConditionally]] based on a [[Param]]
- */
- def paramGated[Query <: PipelineQuery](
- selectors: Seq[Selector[Query]],
- enabledParam: Param[Boolean],
- ): Seq[Selector[Query]] =
- selectors.map(SelectConditionally.paramGated(_, enabledParam))
-
- /**
- * A [[SelectConditionally]] based on an inverted [[Param]]
- */
- def paramNotGated[Query <: PipelineQuery](
- selector: Selector[Query],
- enabledParamToInvert: Param[Boolean],
- ): SelectConditionally[Query] =
- SelectConditionally(selector, (query, _, _) => !query.params(enabledParamToInvert))
-
- /**
- * Wrap each [[Selector]] in `selectors` in a [[SelectConditionally]] based on an inverted [[Param]]
- */
- def paramNotGated[Query <: PipelineQuery](
- selectors: Seq[Selector[Query]],
- enabledParamToInvert: Param[Boolean],
- ): Seq[Selector[Query]] =
- selectors.map(SelectConditionally.paramNotGated(_, enabledParamToInvert))
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala
deleted file mode 100644
index 86ff297b7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import scala.reflect.ClassTag
-
-sealed trait SubpoolIncludeTypes
-
-trait IncludeInSubpool[-Query <: PipelineQuery] extends SubpoolIncludeTypes {
-
- /**
- * Given the `query`, current `remainingCandidate`, and the `result`,
- * returns whether the specific `remainingCandidate` should be passed into the
- * [[SelectFromSubpoolCandidates]]'s [[SelectFromSubpoolCandidates.selector]]
- *
- * @note the `result` contains the [[SelectorResult.result]] that was passed into this selector,
- * so each `remainingCandidate` will get the same `result` Seq.
- */
- def apply(
- query: Query,
- remainingCandidate: CandidateWithDetails,
- result: Seq[CandidateWithDetails]
- ): Boolean
-}
-
-case class IncludeCandidateTypeInSubpool[CandidateType <: UniversalNoun[_]](
-)(
- implicit tag: ClassTag[CandidateType])
- extends IncludeInSubpool[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidate: CandidateWithDetails,
- result: Seq[CandidateWithDetails]
- ): Boolean = remainingCandidate.isCandidateType[CandidateType]()
-}
-
-trait IncludeSetInSubpool[-Query <: PipelineQuery] extends SubpoolIncludeTypes {
-
- /**
- * Given the `query`, all `remainingCandidates`` and `results`,
- * returns a Set of which candidates should be included in the subpool.
- *
- * @note the returned set is only used to determine subpool membership. Mutating the candidates
- * is invalid and won't work. The order of the candidates will be preserved from the current
- * order of the remaining candidates sequence.
- */
- def apply(
- query: Query,
- remainingCandidate: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Set[CandidateWithDetails]
-}
-
-sealed trait SubpoolRemainingCandidatesHandler
-
-/**
- * Candidates remaining in the subpool after running the selector will be
- * prepended to the beginning of the [[SelectorResult.remainingCandidates]]
- */
-case object PrependToBeginningOfRemainingCandidates extends SubpoolRemainingCandidatesHandler
-
-/**
- * Candidates remaining in the subpool after running the selector will be
- * appended to the end of the [[SelectorResult.remainingCandidates]]
- */
-case object AppendToEndOfRemainingCandidates extends SubpoolRemainingCandidatesHandler
-
-/**
- * Creates a subpool of all `remainingCandidates` for which [[subpoolInclude]] resolves to true
- * (in the same order as the original `remainingCandidates`) and runs the [[selector]] with the
- * subpool passed in as the `remainingCandidates`.
- *
- * Most customers want to use a IncludeInSubpool that chooses if each candidate should be included
- * in the subpool.
- * Where necessary, IncludeSetInSubpool allows you to define them in bulk w/ a Set.
- *
- * @note any candidates in the subpool which are not added to the [[SelectorResult.result]]
- * will be treated according to the [[SubpoolRemainingCandidatesHandler]]
- */
-class SelectFromSubpoolCandidates[-Query <: PipelineQuery] private[selector] (
- val selector: Selector[Query],
- subpoolInclude: SubpoolIncludeTypes,
- subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler =
- AppendToEndOfRemainingCandidates)
- extends Selector[Query] {
-
- override val pipelineScope: CandidateScope = selector.pipelineScope
-
- override def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
-
- val (selectedCandidates, otherCandidates) = subpoolInclude match {
- case includeInSubpool: IncludeInSubpool[Query] =>
- remainingCandidates.partition(candidate =>
- pipelineScope.contains(candidate) && includeInSubpool(query, candidate, result))
- case includeSetInSubpool: IncludeSetInSubpool[Query] =>
- val includeSet =
- includeSetInSubpool(query, remainingCandidates.filter(pipelineScope.contains), result)
- remainingCandidates.partition(candidate => includeSet.contains(candidate))
- }
-
- val underlyingSelectorResult = selector.apply(query, selectedCandidates, result)
- val remainingCandidatesWithSubpoolRemainingCandidates =
- subpoolRemainingCandidatesHandler match {
- case AppendToEndOfRemainingCandidates =>
- otherCandidates ++ underlyingSelectorResult.remainingCandidates
- case PrependToBeginningOfRemainingCandidates =>
- underlyingSelectorResult.remainingCandidates ++ otherCandidates
- }
- underlyingSelectorResult.copy(remainingCandidates =
- remainingCandidatesWithSubpoolRemainingCandidates)
- }
-
- override def toString: String = s"SelectFromSubpoolCandidates(${selector.toString}))"
-}
-
-object SelectFromSubpoolCandidates {
- def apply[Query <: PipelineQuery](
- selector: Selector[Query],
- includeInSubpool: IncludeInSubpool[Query],
- subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler =
- AppendToEndOfRemainingCandidates
- ) = new SelectFromSubpoolCandidates[Query](
- selector,
- includeInSubpool,
- subpoolRemainingCandidatesHandler
- )
-
- def includeSet[Query <: PipelineQuery](
- selector: Selector[Query],
- includeSetInSubpool: IncludeSetInSubpool[Query],
- subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler =
- AppendToEndOfRemainingCandidates
- ) = new SelectFromSubpoolCandidates[Query](
- selector,
- includeSetInSubpool,
- subpoolRemainingCandidatesHandler
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala
deleted file mode 100644
index 235bcf778..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering
-import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector._
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UpdateSortCandidates {
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- sorterProvider: SorterProvider,
- ) = new UpdateSortCandidates(SpecificPipeline(candidatePipeline), sorterProvider)
-
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- ordering: Ordering[CandidateWithDetails]
- ) =
- new UpdateSortCandidates(SpecificPipeline(candidatePipeline), SorterFromOrdering(ordering))
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier],
- ordering: Ordering[CandidateWithDetails]
- ) =
- new UpdateSortCandidates(SpecificPipelines(candidatePipelines), SorterFromOrdering(ordering))
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier],
- sorterProvider: SorterProvider,
- ) = new UpdateSortCandidates(SpecificPipelines(candidatePipelines), sorterProvider)
-
- def apply(
- pipelineScope: CandidateScope,
- ordering: Ordering[CandidateWithDetails]
- ) = new UpdateSortCandidates(pipelineScope, SorterFromOrdering(ordering))
-}
-
-/**
- * Sort item and module (not items inside modules) candidates in a pipeline scope.
- * Note that if sorting across multiple candidate sources, the candidates will be grouped together
- * in sorted order, starting from the position of the first candidate.
- *
- * For example, we could specify the following ordering to sort by score descending:
- * Ordering
- * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match {
- * case Scored(score) => score
- * case _ => Double.MinValue
- * }).reverse
- */
-case class UpdateSortCandidates(
- override val pipelineScope: CandidateScope,
- sorterProvider: SorterProvider)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val PartitionedCandidates(selectedCandidates, otherCandidates) =
- pipelineScope.partition(remainingCandidates)
-
- val updatedRemainingCandidates = if (selectedCandidates.nonEmpty) {
- // Safe .head due to nonEmpty check
- val position = remainingCandidates.indexOf(selectedCandidates.head)
- val orderedSelectedCandidates =
- sorterProvider.sorter(query, remainingCandidates, result).sort(selectedCandidates)
-
- if (position < otherCandidates.length) {
- val (left, right) = otherCandidates.splitAt(position)
- left ++ orderedSelectedCandidates ++ right
- } else {
- otherCandidates ++ orderedSelectedCandidates
- }
- } else {
- remainingCandidates
- }
-
- SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala
deleted file mode 100644
index 33de20999..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering
-import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UpdateSortModuleItemCandidates {
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- ordering: Ordering[CandidateWithDetails]
- ): UpdateSortModuleItemCandidates =
- UpdateSortModuleItemCandidates(
- SpecificPipeline(candidatePipeline),
- SorterFromOrdering(ordering))
-
- def apply(
- candidatePipeline: CandidatePipelineIdentifier,
- sorterProvider: SorterProvider
- ): UpdateSortModuleItemCandidates =
- UpdateSortModuleItemCandidates(SpecificPipeline(candidatePipeline), sorterProvider)
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier],
- ordering: Ordering[CandidateWithDetails]
- ): UpdateSortModuleItemCandidates =
- UpdateSortModuleItemCandidates(
- SpecificPipelines(candidatePipelines),
- SorterFromOrdering(ordering))
-
- def apply(
- candidatePipelines: Set[CandidatePipelineIdentifier],
- sorterProvider: SorterProvider
- ): UpdateSortModuleItemCandidates =
- UpdateSortModuleItemCandidates(SpecificPipelines(candidatePipelines), sorterProvider)
-}
-
-/**
- * Sort items inside a module from a candidate source and update the remainingCandidates.
- *
- * For example, we could specify the following ordering to sort by score descending:
- *
- * {{{
- * Ordering
- * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match {
- * case Scored(score) => score
- * case _ => Double.MinValue
- * }).reverse
- *
- * // Before sorting:
- * ModuleCandidateWithDetails(
- * Seq(
- * ItemCandidateWithLowScore,
- * ItemCandidateWithMidScore,
- * ItemCandidateWithHighScore),
- * ... other params
- * )
- *
- * // After sorting:
- * ModuleCandidateWithDetails(
- * Seq(
- * ItemCandidateWithHighScore,
- * ItemCandidateWithMidScore,
- * ItemCandidateWithLowScore),
- * ... other params
- * )
- * }}}
- *
- * @note this updates the modules in the `remainingCandidates`
- */
-case class UpdateSortModuleItemCandidates(
- override val pipelineScope: CandidateScope,
- sorterProvider: SorterProvider)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val updatedCandidates = remainingCandidates.map {
- case module: ModuleCandidateWithDetails if pipelineScope.contains(module) =>
- module.copy(candidates =
- sorterProvider.sorter(query, remainingCandidates, result).sort(module.candidates))
- case candidate => candidate
- }
- SelectorResult(remainingCandidates = updatedCandidates, result = result)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala
deleted file mode 100644
index 76785780f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.component_library.selector
-
-import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering
-import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object UpdateSortResults {
- def apply(
- ordering: Ordering[CandidateWithDetails]
- ) =
- new UpdateSortResults((_, _, _) => SorterFromOrdering(ordering))
-}
-
-/**
- * Sort item and module (not items inside modules) results.
- *
- * For example, we could specify the following ordering to sort by score descending:
- * Ordering
- * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match {
- * case Scored(score) => score
- * case _ => Double.MinValue
- * }).reverse
- */
-case class UpdateSortResults(
- sorterProvider: SorterProvider,
- override val pipelineScope: CandidateScope = AllPipelines)
- extends Selector[PipelineQuery] {
-
- override def apply(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- val updatedResult = sorterProvider.sorter(query, remainingCandidates, result).sort(result)
-
- SelectorResult(remainingCandidates = remainingCandidates, result = updatedResult)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala
deleted file mode 100644
index 21d811ee7..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.ads
-
-import com.google.inject.Inject
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.goldfinch.adaptors.ads.productmixer.ProductMixerPromotedEntriesAdaptor
-import com.twitter.goldfinch.adaptors.productmixer.ProductMixerNonPromotedEntriesAdaptor
-import com.twitter.goldfinch.adaptors.productmixer.ProductMixerQueryConverter
-import com.twitter.goldfinch.api.AdsInjectionRequestContextConverter
-import com.twitter.goldfinch.api.AdsInjectionSurfaceAreas.SurfaceAreaName
-import com.twitter.goldfinch.api.{AdsInjector => GoldfinchAdsInjector}
-import com.twitter.goldfinch.api.NonPromotedEntriesAdaptor
-import com.twitter.goldfinch.api.PromotedEntriesAdaptor
-import com.twitter.goldfinch.impl.injector.AdsInjectorBuilder
-import com.twitter.goldfinch.impl.injector.product_mixer.AdsInjectionSurfaceAreaAdjustersMap
-import com.twitter.goldfinch.impl.injector.product_mixer.VerticalSizeAdjustmentConfigMap
-import com.twitter.inject.Logging
-import com.twitter.product_mixer.component_library.model.query.ads._
-import com.twitter.product_mixer.core.model.common.presentation._
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import javax.inject.Singleton
-import com.twitter.goldfinch.impl.core.DefaultFeatureSwitchResultsFactory
-import com.twitter.goldfinch.impl.core.LocalDevelopmentFeatureSwitchResultsFactory
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ConfigRepoLocalPath
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-
-@Singleton
-class AdsInjector @Inject() (
- statsReceiver: StatsReceiver,
- @Flag(ConfigRepoLocalPath) localConfigRepoPath: String,
- @Flag(ServiceLocal) isServiceLocal: Boolean)
- extends Logging {
- private val adsQueryRequestConverter: AdsInjectionRequestContextConverter[
- PipelineQuery with AdsQuery
- ] = ProductMixerQueryConverter
-
- def forSurfaceArea(
- surfaceAreaName: SurfaceAreaName
- ): GoldfinchAdsInjector[
- PipelineQuery with AdsQuery,
- CandidateWithDetails,
- CandidateWithDetails
- ] = {
-
- val scopedStatsReceiver: StatsReceiver =
- statsReceiver.scope("goldfinch", surfaceAreaName.toString)
-
- val nonAdsAdaptor: NonPromotedEntriesAdaptor[CandidateWithDetails] =
- ProductMixerNonPromotedEntriesAdaptor(
- VerticalSizeAdjustmentConfigMap.configsBySurfaceArea(surfaceAreaName),
- scopedStatsReceiver)
-
- val adsAdaptor: PromotedEntriesAdaptor[CandidateWithDetails] =
- new ProductMixerPromotedEntriesAdaptor(scopedStatsReceiver)
-
- val featureSwitchFactory = if (isServiceLocal) {
- new LocalDevelopmentFeatureSwitchResultsFactory(
- surfaceAreaName.toString,
- configRepoAbsPath = localConfigRepoPath)
- } else new DefaultFeatureSwitchResultsFactory(surfaceAreaName.toString)
-
- new AdsInjectorBuilder[PipelineQuery with AdsQuery, CandidateWithDetails, CandidateWithDetails](
- requestAdapter = adsQueryRequestConverter,
- nonPromotedEntriesAdaptor = nonAdsAdaptor,
- promotedEntriesAdaptor = adsAdaptor,
- adjusters =
- AdsInjectionSurfaceAreaAdjustersMap.getAdjusters(surfaceAreaName, scopedStatsReceiver),
- featureSwitchFactory = featureSwitchFactory,
- statsReceiver = scopedStatsReceiver,
- logger = logger
- ).build()
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel
deleted file mode 100644
index 6536b7cf4..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/ads/productmixer",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/ads/productmixer/util",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/productmixer",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/api",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/core",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector",
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector/product_mixer",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
- exports = [
- "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala
deleted file mode 100644
index 54eab9e69..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.ads
-
-import com.twitter.goldfinch.api.AdsInjectionSurfaceAreas.SurfaceAreaName
-import com.twitter.goldfinch.api.AdsInjectorAdditionalRequestParams
-import com.twitter.goldfinch.api.AdsInjectorOutput
-import com.twitter.goldfinch.api.{AdsInjector => GoldfinchAdsInjector}
-import com.twitter.product_mixer.component_library.model.query.ads._
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import CandidateScope.PartitionedCandidates
-import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Injects the sequence of AdCandidates in the `result` in the
- * sequence of the Other Candidates(which are not ads).
- *
- * Every SurfaceArea or DisplayLocation runs their own desired set of adjusters(set in pipeline)
- * to inject ads and reposition the ads in the sequence of other candidates of `result` :
- * which are fetched by AdsInjectionSurfaceAreaAdjustersMap
- * Note: The original sequence of non_promoted entries(non-ads) is retained and the ads
- * are inserted in the sequence using `goldfinch` library based on the 'insertion-position'
- * hydrated in AdsCandidate by Adserver/Admixer.
- *
- * ***** Goldfinch recommends to run this selector as close to the marshalling of candidates to have
- * more realistic view of served-timeline in Goldfinch-BQ-Logs and avoid any further updates on the
- * timeline(sequence of entries) created. ****
- *
- * Any surface area like `search_tweets(surface_area)` can call
- * InsertAdResults(surfaceArea = "TweetSearch", candidatePipeline = adsCandidatePipeline.identifier,
- * ProductMixerAdsInjector = productMixerAdsInjector)
- * where the pipeline config can call
- * productMixerAdsInjector.forSurfaceArea("TweetSearch") to get AdsInjector Object
- *
- * @example
- * `Seq(source1NonAd_Id1, source1NonAd_Id2, source2NonAd_Id1, source2NonAd_Id2,source1NonAd_Id3, source3NonAd_Id3,source3Ad_Id1_InsertionPos1, source3Ad_Id2_InsertionPos4)`
- * then the output result can be
- * `Seq(source1NonAd_Id1, source3Ad_Id1_InsertionPos1, source1NonAd_Id2, source2NonAd_Id1, source3Ad_Id2_InsertionPos4,source2NonAd_Id2, source1NonAd_Id3, source3NonAd_Id3)`
- * depending on the insertion position of Ads and other adjusters shifting the ads
- */
-case class InsertAdResults(
- surfaceAreaName: SurfaceAreaName,
- adsInjector: GoldfinchAdsInjector[
- PipelineQuery with AdsQuery,
- CandidateWithDetails,
- CandidateWithDetails
- ],
- adsCandidatePipeline: CandidatePipelineIdentifier)
- extends Selector[PipelineQuery with AdsQuery] {
-
- override val pipelineScope: CandidateScope = SpecificPipeline(adsCandidatePipeline)
-
- override def apply(
- query: PipelineQuery with AdsQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult = {
- // Read into ads and non-ads candidates.
- val PartitionedCandidates(adCandidates, otherRemainingCandidates) =
- pipelineScope.partition(remainingCandidates)
-
- // Create this param from Query/AdsCandidate based on surface_area, if required.
- val adsInjectorAdditionalRequestParams =
- AdsInjectorAdditionalRequestParams(budgetAwareExperimentId = None)
-
- val adsInjectorOutput: AdsInjectorOutput[CandidateWithDetails, CandidateWithDetails] =
- adsInjector.applyForAllEntries(
- query = query,
- nonPromotedEntries = result,
- promotedEntries = adCandidates,
- adsInjectorAdditionalRequestParams = adsInjectorAdditionalRequestParams)
-
- val updatedRemainingCandidates = otherRemainingCandidates ++
- GoldfinchResults(adsInjectorOutput.unusedEntries).adapt
- val mergedResults = GoldfinchResults(adsInjectorOutput.mergedEntries).adapt
- SelectorResult(remainingCandidates = updatedRemainingCandidates, result = mergedResults)
- }
-
- /**
- * Goldfinch separates NonPromotedEntryType and PromotedEntryType models, while in ProMix both
- * non-promoted and promoted entries are CandidateWithDetails. As such, we need to flatten the
- * result back into a single Seq of CandidateWithDetails. See [[AdsInjectorOutput]]
- */
- case class GoldfinchResults(results: Seq[Either[CandidateWithDetails, CandidateWithDetails]]) {
- def adapt: Seq[CandidateWithDetails] = {
- results.collect {
- case Right(value) => value
- case Left(value) => value
- }
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD
deleted file mode 100644
index a1c0b286f..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD
+++ /dev/null
@@ -1,20 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala
deleted file mode 100644
index f1940f312..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala
+++ /dev/null
@@ -1,248 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import scala.reflect.runtime.universe._
-
-object FeatureValueSorter {
-
- /**
- * Sort by a feature value ascending. If the feature failed or is missing, use an inferred default
- * based on the type of [[FeatureValue]]. For Numeric values this is the MinValue
- * (e.g. Long.MinValue, Double.MinValue).
- *
- * @param feature feature with value to sort by
- * @param dummyImplicit due to type erasure, implicit used to disambiguate `def ascending()`
- * between def with param `feature: Feature[Candidate, FeatureValue]`
- * from def with param `feature: Feature[Candidate, Option[FeatureValue]]`
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[featureValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, FeatureValue]
- )(
- implicit dummyImplicit: DummyImplicit,
- typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Ascending)
-
- ascending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by a feature value ascending. If the feature failed or is missing, use the provided
- * default.
- *
- * @param feature feature with value to sort by
- * @param dummyImplicit due to type erasure, implicit used to disambiguate `def ascending()`
- * between def with param `feature: Feature[Candidate, FeatureValue]`
- * from def with param `feature: Feature[Candidate, Option[FeatureValue]]`
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, FeatureValue],
- defaultFeatureValue: FeatureValue
- )(
- implicit dummyImplicit: DummyImplicit
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElse(feature, defaultFeatureValue))
-
- SorterFromOrdering(ordering, Ascending)
- }
-
- /**
- * Sort by an optional feature value ascending. If the feature failed or is missing, use an
- * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MinValue
- * (e.g. Long.MinValue, Double.MinValue).
- *
- * @param feature feature with value to sort by
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[featureOptionalValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, Option[FeatureValue]]
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue = featureOptionalValueSortDefaultValue(feature, Ascending)
-
- ascending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by an optional feature value ascending. If the feature failed or is missing, use the
- * provided default.
- *
- * @param feature feature with value to sort by
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, Option[FeatureValue]],
- defaultFeatureValue: FeatureValue
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElse(feature, None).getOrElse(defaultFeatureValue))
-
- SorterFromOrdering(ordering, Ascending)
- }
-
- /**
- * Sort by a feature value descending. If the feature failed or is missing, use an inferred
- * default based on the type of [[FeatureValue]]. For Numeric values this is the MaxValue
- * (e.g. Long.MaxValue, Double.MaxValue).
- *
- * @param feature feature with value to sort by
- * @param dummyImplicit due to type erasure, implicit used to disambiguate `def descending()`
- * between def with param `feature: Feature[Candidate, FeatureValue]`
- * from def with param `feature: Feature[Candidate, Option[FeatureValue]]`
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[featureValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, FeatureValue]
- )(
- implicit dummyImplicit: DummyImplicit,
- typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Descending)
-
- descending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by a feature value descending. If the feature failed or is missing, use the provided
- * default.
- *
- * @param feature feature with value to sort by
- * @param dummyImplicit due to type erasure, implicit used to disambiguate `def descending()`
- * between def with param `feature: Feature[Candidate, FeatureValue]`
- * from def with param `feature: Feature[Candidate, Option[FeatureValue]]`
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, FeatureValue],
- defaultFeatureValue: FeatureValue
- )(
- implicit dummyImplicit: DummyImplicit
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElse(feature, defaultFeatureValue))
-
- SorterFromOrdering(ordering, Descending)
- }
-
- /**
- * Sort by an optional feature value descending. If the feature failed or is missing, use an
- * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MaxValue
- * (e.g. Long.MaxValue, Double.MaxValue).
- *
- * @param feature feature with value to sort by
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[featureOptionalValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, Option[FeatureValue]]
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue =
- featureOptionalValueSortDefaultValue(feature, Descending)
-
- descending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by an optional feature value descending. If the feature failed or is missing, use the
- * provided default.
- *
- * @param feature feature with value to sort by
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: Feature[Candidate, Option[FeatureValue]],
- defaultFeatureValue: FeatureValue
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElse(feature, None).getOrElse(defaultFeatureValue))
-
- SorterFromOrdering(ordering, Descending)
- }
-
- private[sorter] def featureValueSortDefaultValue[FeatureValue: Ordering](
- feature: Feature[_, FeatureValue],
- sortOrder: SortOrder
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): FeatureValue = {
- val defaultValue = sortOrder match {
- case Descending =>
- typeOf[FeatureValue] match {
- case t if t <:< typeOf[Short] => Short.MinValue
- case t if t <:< typeOf[Int] => Int.MinValue
- case t if t <:< typeOf[Long] => Long.MinValue
- case t if t <:< typeOf[Double] => Double.MinValue
- case t if t <:< typeOf[Float] => Float.MinValue
- case _ =>
- throw new UnsupportedOperationException(s"Default value not supported for $feature")
- }
- case Ascending =>
- typeOf[FeatureValue] match {
- case t if t <:< typeOf[Short] => Short.MaxValue
- case t if t <:< typeOf[Int] => Int.MaxValue
- case t if t <:< typeOf[Long] => Long.MaxValue
- case t if t <:< typeOf[Double] => Double.MaxValue
- case t if t <:< typeOf[Float] => Float.MaxValue
- case _ =>
- throw new UnsupportedOperationException(s"Default value not supported for $feature")
- }
- }
-
- defaultValue.asInstanceOf[FeatureValue]
- }
-
- private[sorter] def featureOptionalValueSortDefaultValue[FeatureValue: Ordering](
- feature: Feature[_, Option[FeatureValue]],
- sortOrder: SortOrder
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): FeatureValue = {
- val defaultValue = sortOrder match {
- case Descending =>
- typeOf[Option[FeatureValue]] match {
- case t if t <:< typeOf[Option[Short]] => Short.MinValue
- case t if t <:< typeOf[Option[Int]] => Int.MinValue
- case t if t <:< typeOf[Option[Long]] => Long.MinValue
- case t if t <:< typeOf[Option[Double]] => Double.MinValue
- case t if t <:< typeOf[Option[Float]] => Float.MinValue
- case _ =>
- throw new UnsupportedOperationException(s"Default value not supported for $feature")
- }
- case Ascending =>
- typeOf[Option[FeatureValue]] match {
- case t if t <:< typeOf[Option[Short]] => Short.MaxValue
- case t if t <:< typeOf[Option[Int]] => Int.MaxValue
- case t if t <:< typeOf[Option[Long]] => Long.MaxValue
- case t if t <:< typeOf[Option[Double]] => Double.MaxValue
- case t if t <:< typeOf[Option[Float]] => Float.MaxValue
- case _ =>
- throw new UnsupportedOperationException(s"Default value not supported for $feature")
- }
- }
-
- defaultValue.asInstanceOf[FeatureValue]
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala
deleted file mode 100644
index 1bd9ee317..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import scala.util.Random
-
-/**
- * Randomly shuffles candidates using the provided [[random]]
- *
- * @example `UpdateSortResults(RandomShuffleSorter())`
- * @param random used to set the seed and for ease of testing, in most cases leaving it as the default is fine.
- */
-case class RandomShuffleSorter(random: Random = new Random(0)) extends SorterProvider with Sorter {
-
- override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] =
- random.shuffle(candidates)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala
deleted file mode 100644
index 418cf2982..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-/**
- * Reverse candidates.
- *
- * @example `UpdateSortResults(ReverseSorter())`
- */
-object ReverseSorter extends SorterProvider with Sorter {
-
- override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] =
- candidates.reverse
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala
deleted file mode 100644
index 3ddd5fc84..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-sealed trait SortOrder
-case object Ascending extends SortOrder
-case object Descending extends SortOrder
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala
deleted file mode 100644
index c09792eb8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-object SorterFromOrdering {
- def apply(ordering: Ordering[CandidateWithDetails], sortOrder: SortOrder): SorterFromOrdering =
- SorterFromOrdering(if (sortOrder == Descending) ordering.reverse else ordering)
-}
-
-/**
- * Sorts candidates based on the provided [[ordering]]
- *
- * @note the [[Ordering]] must be transitive, so if `A < B` and `B < C` then `A < C`.
- * @note sorting randomly via `Ordering.by[CandidateWithDetails, Double](_ => Random.nextDouble())`
- * is not safe and can fail at runtime since TimSort depends on stable sort values for
- * pivoting. To sort randomly, use [[RandomShuffleSorter]] instead.
- */
-case class SorterFromOrdering(
- ordering: Ordering[CandidateWithDetails])
- extends SorterProvider
- with Sorter {
-
- override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] =
- candidates.sorted(ordering)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala
deleted file mode 100644
index d0c1a3eb2..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Makes a [[Sorter]] to run for the given input based on the
- * [[PipelineQuery]], the `remainingCandidates`, and the `result`.
- *
- * @note this should be used to choose between different [[Sorter]]s,
- * if you want to conditionally sort wrap your [[Sorter]] with
- * [[com.twitter.product_mixer.component_library.selector.SelectConditionally]] instead.
- */
-trait SorterProvider {
-
- /** Makes a [[Sorter]] for the given inputs */
- def sorter(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Sorter
-}
-
-/**
- * Sorts the candidates
- *
- * All [[Sorter]]s also implement [[SorterProvider]] to provide themselves for convenience.
- */
-trait Sorter { self: SorterProvider =>
-
- /** Sorts the `candidates` */
- def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate]
-
- /** Any [[Sorter]] can be used in place of a [[SorterProvider]] to provide itself */
- override final def sorter(
- query: PipelineQuery,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): Sorter = self
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD
deleted file mode 100644
index a074c678b..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- scalac_plugins = ["no-roomba"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala
deleted file mode 100644
index b4819e6a8..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.twitter.product_mixer.component_library.selector.sorter.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.component_library.selector.sorter.Ascending
-import com.twitter.product_mixer.component_library.selector.sorter.Descending
-import com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue
-import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering
-import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider
-import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import scala.reflect.runtime.universe._
-
-/**
- * Feature Store v1 version of [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter]]
- */
-object FeatureStoreV1FeatureValueSorter {
-
- /**
- * Sort by a Feature Store v1 feature value ascending. If the feature failed or is missing, use an
- * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MinValue
- * (e.g. Long.MinValue, Double.MinValue).
- *
- * @param feature Feature Store v1 feature with value to sort by
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue]
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Ascending)
-
- ascending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by a Feature Store v1 feature value ascending. If the feature failed or is missing, use
- * the provided default.
- *
- * @param feature Feature Store v1 feature with value to sort by
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue],
- defaultFeatureValue: FeatureValue
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElseFeatureStoreV1CandidateFeature(feature, defaultFeatureValue))
-
- SorterFromOrdering(ordering, Ascending)
- }
-
- /**
- * Sort by a Feature Store v1 feature value descending. If the feature failed or is missing, use
- * an inferred default based on the type of [[FeatureValue]]. For Numeric values this is the
- * MaxValue (e.g. Long.MaxValue, Double.MaxValue).
- *
- * @param feature Feature Store v1 feature with value to sort by
- * @param typeTag allows for inferring default value from the FeatureValue type.
- * See [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue]]
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue]
- )(
- implicit typeTag: TypeTag[FeatureValue]
- ): SorterProvider = {
- val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Descending)
-
- descending(feature, defaultFeatureValue)
- }
-
- /**
- * Sort by a Feature Store v1 feature value descending. If the feature failed or is missing, use
- * the provided default.
- *
- * @param feature Feature Store v1 feature with value to sort by
- * @tparam Candidate candidate for the feature
- * @tparam FeatureValue feature value with an [[Ordering]] context bound
- */
- def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering](
- feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue],
- defaultFeatureValue: FeatureValue
- ): SorterProvider = {
- val ordering = Ordering.by[CandidateWithDetails, FeatureValue](
- _.features.getOrElseFeatureStoreV1CandidateFeature(feature, defaultFeatureValue))
-
- SorterFromOrdering(ordering, Descending)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD
deleted file mode 100644
index 9d3a2bc80..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin",
- "abdecider/src/main/scala:abdeciderutils",
- "decider/src/main/scala",
- "finatra-internal/messaging/kafka/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers",
- "scribelib/validators/src/main/scala/com/twitter/scribelib/validators",
- "scrooge/scrooge-serializer/src/main/scala",
- "src/thrift/com/twitter/clientapp/gen:clientapp-scala",
- "stitch/stitch-core",
- "strato/src/main/scala/com/twitter/strato/client",
- "user_session_store/src/main/scala/com/twitter/user_session_store",
- "util/util-core:util-core-util",
- ],
- exports = [
- "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "scrooge/scrooge-serializer/src/main/scala",
- "src/thrift/com/twitter/clientapp/gen:clientapp-scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala
deleted file mode 100644
index 5bda25844..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala
+++ /dev/null
@@ -1,233 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.conversions.StorageUnitOps._
-import com.twitter.finatra.kafka.producers.FinagleKafkaProducerBuilder
-import com.twitter.finatra.kafka.producers.KafkaProducerBase
-import com.twitter.finatra.kafka.producers.TwitterKafkaProducerConfig
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.util.Duration
-import com.twitter.util.StorageUnit
-import org.apache.kafka.clients.producer.ProducerRecord
-import org.apache.kafka.common.serialization.Serializer
-import org.apache.kafka.common.record.CompressionType
-
-/**
- * The Kafka publishing side effect.
- * This class creates a Kafka producer with provided and default parameters.
- * Note that callers may not provide arbitrary params as this class will do validity check on some
- * params, e.g. maxBlock, to make sure it is safe for online services.
- *
- * PLEASE NOTE: caller needs to add the following to the Aurora file to successfully enable the TLS
- * '-com.twitter.finatra.kafka.producers.principal={{role}}',
- *
- * @tparam K type of the key
- * @tparam V type of the value
- * @tparam Query pipeline query
- */
-trait KafkaPublishingSideEffect[K, V, Query <: PipelineQuery, ResponseType <: HasMarshalling]
- extends PipelineResultSideEffect[Query, ResponseType] {
-
- /**
- * Kafka servers list. It is usually a WilyNs name at Twitter
- */
- val bootstrapServer: String
-
- /**
- * The serde of the key
- */
- val keySerde: Serializer[K]
-
- /**
- * The serde of the value
- */
- val valueSerde: Serializer[V]
-
- /**
- * An id string to pass to the server when making requests.
- * The purpose of this is to be able to track the source of requests beyond just ip/port by
- * allowing a logical application name to be included in server-side request logging.
- */
- val clientId: String
-
- /**
- * The configuration controls how long KafkaProducer.send()
and
- * KafkaProducer.partitionsFor()
will block.
- * These methods can be blocked either because the buffer is full or metadata unavailable.
- * Blocking in the user-supplied serializers or partitioner will not be counted against this timeout.
- *
- * Set 200ms by default to not blocking the thread too long which is critical to most ProMixer
- * powered services. Please note that there is a hard limit check of not greater than 1 second.
- *
- */
- val maxBlock: Duration = 200.milliseconds
-
- /**
- * Retries due to broker failures, etc., may write duplicates of the retried message in the
- * stream. Note that enabling idempotence requires
- * MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION
to be less than or equal to 5,
- * RETRIES_CONFIG
to be greater than 0 and ACKS_CONFIG
- * must be 'all'. If these values are not explicitly set by the user, suitable values will be
- * chosen. If incompatible values are set, a ConfigException
will be thrown.
- *
- * false by default, setting to true may introduce issues to brokers since brokers will keep
- * tracking all requests which is resource expensive.
- */
- val idempotence: Boolean = false
-
- /**
- * The producer will attempt to batch records together into fewer requests whenever multiple
- * records are being sent to the same partition. This helps performance on both the client and
- * the server. This configuration controls the default batch size in bytes.
- * No attempt will be made to batch records larger than this size.
- * Requests sent to brokers will contain multiple batches, one for each partition with data
- * available to be sent. A small batch size will make batching less common and may reduce
- * throughput (a batch size of zero will disable batching entirely).
- * A very large batch size may use memory a bit more wastefully as we will always allocate a
- * buffer of the specified batch size in anticipation of additional records.
- *
- * Default 16KB which comes from Kafka's default
- */
- val batchSize: StorageUnit = 16.kilobytes
-
- /**
- * The producer groups together any records that arrive in between request transmissions into
- * a single batched request. "Normally this occurs only under load when records arrive faster
- * than they can be sent out. However in some circumstances the client may want to reduce the
- * number of requests even under moderate load. This setting accomplishes this by adding a
- * small amount of artificial delay—that is, rather than immediately sending out a record
- * the producer will wait for up to the given delay to allow other records to be sent so that
- * the sends can be batched together. This can be thought of as analogous to Nagle's algorithm
- * in TCP. This setting gives the upper bound on the delay for batching: once we get
- * BATCH_SIZE_CONFIG worth of records for a partition it will be sent immediately regardless
- * of this setting, however if we have fewer than this many bytes accumulated for this
- * partition we will 'linger' for the specified time waiting for more records to show up.
- * This setting defaults to 0 (i.e. no delay). Setting LINGER_MS_CONFIG=5, for example,
- * would have the effect of reducing the number of requests sent but would add up to 5ms of
- * latency to records sent in the absence of load.
- *
- * Default 0ms, which is Kafka's default. If the record size is much larger than the batchSize,
- * you may consider to enlarge both batchSize and linger to have better compression (only when
- * compression is enabled.)
- */
- val linger: Duration = 0.milliseconds
-
- /**
- * The total bytes of memory the producer can use to buffer records waiting to be sent to the
- * server. If records are sent faster than they can be delivered to the server the producer
- * will block for MAX_BLOCK_MS_CONFIG after which it will throw an exception.
- * This setting should correspond roughly to the total memory the producer will use, but is not
- * a hard bound since not all memory the producer uses is used for buffering.
- * Some additional memory will be used for compression (if compression is enabled) as well as
- * for maintaining in-flight requests.
- *
- * Default 32MB which is Kafka's default. Please consider to enlarge this value if the EPS and
- * the per-record size is large (millions EPS with >1KB per-record size) in case the broker has
- * issues (which fills the buffer pretty quickly.)
- */
- val bufferMemorySize: StorageUnit = 32.megabytes
-
- /**
- * Producer compression type
- *
- * Default LZ4 which is a good tradeoff between compression and efficiency.
- * Please be careful of choosing ZSTD, which the compression rate is better it might introduce
- * huge burden to brokers once the topic is consumed, which needs decompression at the broker side.
- */
- val compressionType: CompressionType = CompressionType.LZ4
-
- /**
- * Setting a value greater than zero will cause the client to resend any request that fails
- * with a potentially transient error
- *
- * Default set to 3, to intentionally reduce the retries.
- */
- val retries: Int = 3
-
- /**
- * The amount of time to wait before attempting to retry a failed request to a given topic
- * partition. This avoids repeatedly sending requests in a tight loop under some failure
- * scenarios
- */
- val retryBackoff: Duration = 1.second
-
- /**
- * The configuration controls the maximum amount of time the client will wait
- * for the response of a request. If the response is not received before the timeout
- * elapses the client will resend the request if necessary or fail the request if
- * retries are exhausted.
- *
- * Default 5 seconds which is intentionally low but not too low.
- * Since Kafka's publishing is async this is in general safe (as long as the bufferMem is not full.)
- */
- val requestTimeout: Duration = 5.seconds
-
- require(
- maxBlock.inMilliseconds <= 1000,
- "We intentionally set the maxBlock to be smaller than 1 second to not block the thread for too long!")
-
- lazy val kafkaProducer: KafkaProducerBase[K, V] = {
- val jaasConfig = TwitterKafkaProducerConfig().configMap
- val builder = FinagleKafkaProducerBuilder[K, V]()
- .keySerializer(keySerde)
- .valueSerializer(valueSerde)
- .dest(bootstrapServer, 1.second) // NOTE: this method blocks!
- .clientId(clientId)
- .maxBlock(maxBlock)
- .batchSize(batchSize)
- .linger(linger)
- .bufferMemorySize(bufferMemorySize)
- .maxRequestSize(4.megabytes)
- .compressionType(compressionType)
- .enableIdempotence(idempotence)
- .maxInFlightRequestsPerConnection(5)
- .retries(retries)
- .retryBackoff(retryBackoff)
- .requestTimeout(requestTimeout)
- .withConfig("acks", "all")
- .withConfig("delivery.timeout.ms", requestTimeout + linger)
-
- builder.withConfig(jaasConfig).build()
- }
-
- /**
- * Build the record to be published to Kafka from query, selections and response
- * @param query PipelineQuery
- * @param selectedCandidates Result after Selectors are executed
- * @param remainingCandidates Candidates which were not selected
- * @param droppedCandidates Candidates dropped during selection
- * @param response Result after Unmarshalling
- * @return A sequence of to-be-published ProducerRecords
- */
- def buildRecords(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResponseType
- ): Seq[ProducerRecord[K, V]]
-
- final override def apply(
- inputs: PipelineResultSideEffect.Inputs[Query, ResponseType]
- ): Stitch[Unit] = {
- val records = buildRecords(
- query = inputs.query,
- selectedCandidates = inputs.selectedCandidates,
- remainingCandidates = inputs.remainingCandidates,
- droppedCandidates = inputs.droppedCandidates,
- response = inputs.response
- )
-
- Stitch
- .collect(
- records
- .map { record =>
- Stitch.callFuture(kafkaProducer.send(record))
- }
- ).unit
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala
deleted file mode 100644
index a84fa1ee3..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.product_mixer.component_library.side_effect.ParamGatedPipelineResultSideEffect.IdentifierPrefix
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.side_effect.ExecuteSynchronously
-import com.twitter.product_mixer.core.functional_component.side_effect.FailOpen
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-/**
- * A [[PipelineResultSideEffect]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this filter on and off
- * @param sideEffect the underlying side effect to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- */
-sealed case class ParamGatedPipelineResultSideEffect[
- -Query <: PipelineQuery,
- ResultType <: HasMarshalling
-] private (
- enabledParam: Param[Boolean],
- sideEffect: PipelineResultSideEffect[Query, ResultType])
- extends PipelineResultSideEffect[Query, ResultType]
- with PipelineResultSideEffect.Conditionally[Query, ResultType] {
- override val identifier: SideEffectIdentifier = SideEffectIdentifier(
- IdentifierPrefix + sideEffect.identifier.name)
- override val alerts: Seq[Alert] = sideEffect.alerts
- override def onlyIf(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResultType
- ): Boolean =
- Conditionally.and(
- PipelineResultSideEffect
- .Inputs(query, selectedCandidates, remainingCandidates, droppedCandidates, response),
- sideEffect,
- query.params(enabledParam))
- override def apply(inputs: PipelineResultSideEffect.Inputs[Query, ResultType]): Stitch[Unit] =
- sideEffect.apply(inputs)
-}
-
-object ParamGatedPipelineResultSideEffect {
-
- val IdentifierPrefix = "ParamGated"
-
- /**
- * A [[PipelineResultSideEffect]] with [[Conditionally]] based on a [[Param]]
- *
- * @param enabledParam the param to turn this filter on and off
- * @param sideEffect the underlying side effect to run when `enabledParam` is true
- * @tparam Query The domain model for the query or request
- */
- def apply[Query <: PipelineQuery, ResultType <: HasMarshalling](
- enabledParam: Param[Boolean],
- sideEffect: PipelineResultSideEffect[Query, ResultType]
- ): ParamGatedPipelineResultSideEffect[Query, ResultType] = {
- sideEffect match {
- case _: FailOpen =>
- new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect)
- with ExecuteSynchronously
- with FailOpen
- case _: ExecuteSynchronously =>
- new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect) with ExecuteSynchronously
- case _ =>
- new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect)
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala
deleted file mode 100644
index bee6ec92e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.abdecider.ScribingABDeciderUtil
-import com.twitter.clientapp.thriftscala.LogEvent
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.scribelib.marshallers
-import com.twitter.scribelib.marshallers.ClientDataProvider
-import com.twitter.scribelib.marshallers.LogEventMarshaller
-
-/**
- * Side effect to log client events server-side. Create an implementation of this trait by
- * defining the `buildClientEvents` method, and the `page` val.
- * The ClientEvent will be automatically converted into a [[LogEvent]] and scribed.
- */
-trait ScribeClientEventSideEffect[
- Query <: PipelineQuery,
- UnmarshalledResponseType <: HasMarshalling]
- extends ScribeLogEventSideEffect[LogEvent, Query, UnmarshalledResponseType] {
-
- /**
- * The page which will be defined in the namespace. This is typically the service name that's scribing
- */
- val page: String
-
- /**
- * Build the client events from query, selections and response
- *
- * @param query PipelineQuery
- * @param selectedCandidates Result after Selectors are executed
- * @param remainingCandidates Candidates which were not selected
- * @param droppedCandidates Candidates dropped during selection
- * @param response Result after Unmarshalling
- */
- def buildClientEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: UnmarshalledResponseType
- ): Seq[ScribeClientEventSideEffect.ClientEvent]
-
- final override def buildLogEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: UnmarshalledResponseType
- ): Seq[LogEvent] = {
- buildClientEvents(
- query = query,
- selectedCandidates = selectedCandidates,
- remainingCandidates = remainingCandidates,
- droppedCandidates = droppedCandidates,
- response = response).flatMap { event =>
- val clientData = clientContextToClientDataProvider(query)
-
- val clientName = ScribingABDeciderUtil.clientForAppId(clientData.clientApplicationId)
-
- val namespaceMap: Map[String, String] = Map(
- "client" -> Some(clientName),
- "page" -> Some(page),
- "section" -> event.namespace.section,
- "component" -> event.namespace.component,
- "element" -> event.namespace.element,
- "action" -> event.namespace.action
- ).collect { case (k, Some(v)) => k -> v }
-
- val data: Map[Any, Any] = Seq(
- event.eventValue.map("event_value" -> _),
- event.latencyMs.map("latency_ms" -> _)
- ).flatten.toMap
-
- val clientEventData = data +
- ("event_namespace" -> namespaceMap) +
- (marshallers.CategoryKey -> "client_event")
-
- LogEventMarshaller.marshal(
- data = clientEventData,
- clientData = clientData
- )
- }
- }
-
- /**
- * Makes a [[ClientDataProvider]] from the [[PipelineQuery.clientContext]] from the [[query]]
- */
- private def clientContextToClientDataProvider(query: Query): ClientDataProvider = {
- new ClientDataProvider {
- override val userId = query.clientContext.userId
- override val guestId = query.clientContext.guestId
- override val personalizationId = None
- override val deviceId = query.clientContext.deviceId
- override val clientApplicationId = query.clientContext.appId
- override val parentApplicationId = None
- override val countryCode = query.clientContext.countryCode
- override val languageCode = query.clientContext.languageCode
- override val userAgent = query.clientContext.userAgent
- override val isSsl = None
- override val referer = None
- override val externalReferer = None
- }
- }
-}
-
-object ScribeClientEventSideEffect {
- case class EventNamespace(
- section: Option[String] = None,
- component: Option[String] = None,
- element: Option[String] = None,
- action: Option[String] = None)
-
- case class ClientEvent(
- namespace: EventNamespace,
- eventValue: Option[Long] = None,
- latencyMs: Option[Long] = None)
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala
deleted file mode 100644
index f27e9190e..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.logpipeline.client.common.EventPublisher
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.scrooge.ThriftStruct
-import com.twitter.stitch.Stitch
-
-/**
- * A [[PipelineResultSideEffect]] that logs [[Thrift]] data may not already be available to Scribe
- */
-trait ScribeLogEventAsyncSideEffect[
- Thrift <: ThriftStruct,
- Query <: PipelineQuery,
- ResponseType <: HasMarshalling]
- extends PipelineResultSideEffect[Query, ResponseType] {
-
- /**
- * Build the log events from query, selections and response
- * @param query PipelineQuery
- * @param selectedCandidates Result after Selectors are executed
- * @param remainingCandidates Candidates which were not selected
- * @param droppedCandidates Candidates dropped during selection
- * @param response Result after Unmarshalling
- * @return LogEvent in thrift
- */
- def buildLogEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResponseType
- ): Stitch[Seq[Thrift]]
-
- val logPipelinePublisher: EventPublisher[Thrift]
-
- final override def apply(
- inputs: PipelineResultSideEffect.Inputs[Query, ResponseType]
- ): Stitch[Unit] = {
- val logEvents = buildLogEvents(
- query = inputs.query,
- selectedCandidates = inputs.selectedCandidates,
- remainingCandidates = inputs.remainingCandidates,
- droppedCandidates = inputs.droppedCandidates,
- response = inputs.response
- )
-
- logEvents.flatMap { logEvents: Seq[Thrift] =>
- Stitch.collect {
- logEvents.map { logEvent =>
- Stitch.callFuture(logPipelinePublisher.publish(logEvent))
- }
- }.unit
- }
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala
deleted file mode 100644
index df9551e15..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.logpipeline.client.common.EventPublisher
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.scrooge.ThriftStruct
-import com.twitter.stitch.Stitch
-
-/**
- * A [[PipelineResultSideEffect]] that logs [[Thrift]] data that's already available to Scribe
- */
-trait ScribeLogEventSideEffect[
- Thrift <: ThriftStruct,
- Query <: PipelineQuery,
- ResponseType <: HasMarshalling]
- extends PipelineResultSideEffect[Query, ResponseType] {
-
- /**
- * Build the log events from query, selections and response
- * @param query PipelineQuery
- * @param selectedCandidates Result after Selectors are executed
- * @param remainingCandidates Candidates which were not selected
- * @param droppedCandidates Candidates dropped during selection
- * @param response Result after Unmarshalling
- * @return LogEvent in thrift
- */
- def buildLogEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResponseType
- ): Seq[Thrift]
-
- val logPipelinePublisher: EventPublisher[Thrift]
-
- final override def apply(
- inputs: PipelineResultSideEffect.Inputs[Query, ResponseType]
- ): Stitch[Unit] = {
- val logEvents = buildLogEvents(
- query = inputs.query,
- selectedCandidates = inputs.selectedCandidates,
- remainingCandidates = inputs.remainingCandidates,
- droppedCandidates = inputs.droppedCandidates,
- response = inputs.response
- )
-
- Stitch
- .collect(
- logEvents
- .map { logEvent =>
- Stitch.callFuture(logPipelinePublisher.publish(logEvent))
- }
- ).unit
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala
deleted file mode 100644
index 77d9b815c..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Inserter
-
-/**
- * Side effect that writes to Strato column's Insert Op. Create an implementation of this trait by
- * defining the `buildEvents` method and providing a Strato Column inserter of type
- * (StratoKeyarg, StratoValue) -> Any.
- * See https://docbird.twitter.biz/strato/ColumnCatalog.html#insert for information about
- * the Insert operation in Strato.
- *
- * @tparam StratoKeyarg Argument used as a key for Strato column. Could be Unit for common use-cases.
- * @tparam StratoValue Value that is inserted at the Strato column.
- * @tparam Query PipelineQuery
- * @tparam DomainResponseType Timeline response that is marshalled to domain model (e.g. URT, Slice etc).
- */
-trait StratoInsertSideEffect[
- StratoKeyarg,
- StratoValue,
- Query <: PipelineQuery,
- DomainResponseType <: HasMarshalling]
- extends PipelineResultSideEffect[Query, DomainResponseType] {
-
- /**
- * Inserter for the InsertOp on a StratoColumn. In Strato, the InsertOp is represented as
- * (Keyarg, Value) => Key, where Key represents the result returned by the Insert operation.
- * For the side-effect behavior, we do not need the return value and use Any instead.
- */
- val stratoInserter: Inserter[StratoKeyarg, StratoValue, Any]
-
- /**
- * Builds the events that are inserted to the Strato column. This method supports generating
- * multiple events for a single side-effect invocation.
- *
- * @param query PipelineQuery
- * @param selectedCandidates Result after Selectors are executed
- * @param remainingCandidates Candidates which were not selected
- * @param droppedCandidates Candidates dropped during selection
- * @param response Timeline response that is marshalled to domain model (e.g. URT, Slice etc).
- * @return Tuples of (StratoKeyArg, StratoValue) that are used to call the stratoInserter.
- */
- def buildEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: DomainResponseType
- ): Seq[(StratoKeyarg, StratoValue)]
-
- final override def apply(
- inputs: PipelineResultSideEffect.Inputs[Query, DomainResponseType]
- ): Stitch[Unit] = {
- val events = buildEvents(
- query = inputs.query,
- selectedCandidates = inputs.selectedCandidates,
- remainingCandidates = inputs.remainingCandidates,
- droppedCandidates = inputs.droppedCandidates,
- response = inputs.response
- )
-
- Stitch
- .traverse(events) { case (keyarg, value) => stratoInserter.insert(keyarg, value) }
- .unit
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala
deleted file mode 100644
index 6199794d6..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect
-
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.user_session_store.ReadWriteUserSessionStore
-import com.twitter.user_session_store.WriteRequest
-
-/**
- * A [[PipelineResultSideEffect]] that writes to a [[ReadWriteUserSessionStore]]
- */
-trait UserSessionStoreUpdateSideEffect[
- Request <: WriteRequest,
- Query <: PipelineQuery,
- ResponseType <: HasMarshalling]
- extends PipelineResultSideEffect[Query, ResponseType] {
-
- /**
- * Build the write request from the query
- * @param query PipelineQuery
- * @return WriteRequest
- */
- def buildWriteRequest(query: Query): Option[Request]
-
- val userSessionStore: ReadWriteUserSessionStore
-
- final override def apply(
- inputs: PipelineResultSideEffect.Inputs[Query, ResponseType]
- ): Stitch[Unit] = {
- buildWriteRequest(inputs.query)
- .map(userSessionStore.write)
- .getOrElse(Stitch.Unit)
- }
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel
deleted file mode 100644
index 7f8229524..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "util/util-core:util-core-util",
- "util/util-slf4j-api/src/main/scala/com/twitter/util/logging",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect",
- ],
-)
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala
deleted file mode 100644
index 1dfcd8865..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect.metrics
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate
-import com.twitter.product_mixer.component_library.side_effect.metrics.CandidateMetricFunction.getCountForType
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-
-/**
- * Function to extract numerical metric value from [[CandidateWithDetails]].
- * This CandidateMetricFunction will be applied on all [[CandidateWithDetails]] instances in the
- * candidateSelection from the RecommendationPipeline.
- */
-trait CandidateMetricFunction {
- def apply(candidateWithDetails: CandidateWithDetails): Long
-}
-
-object CandidateMetricFunction {
-
- private val defaultCountOnePf: PartialFunction[CandidateWithDetails, Long] = {
- case _ => 0L
- }
-
- /**
- * Count the occurrences of a certain candidate type from [[CandidateWithDetails]].
- */
- def getCountForType(
- candidateWithDetails: CandidateWithDetails,
- countOnePf: PartialFunction[CandidateWithDetails, Long]
- ): Long = {
- (countOnePf orElse defaultCountOnePf)(candidateWithDetails)
- }
-}
-
-object DefaultServedTweetsSumFunction extends CandidateMetricFunction {
- override def apply(candidateWithDetails: CandidateWithDetails): Long =
- getCountForType(
- candidateWithDetails,
- {
- case item: ItemCandidateWithDetails =>
- item.candidate match {
- case _: BaseTweetCandidate => 1L
- case _ => 0L
- }
- })
-}
-
-object DefaultServedUsersSumFunction extends CandidateMetricFunction {
- override def apply(candidateWithDetails: CandidateWithDetails): Long =
- getCountForType(
- candidateWithDetails,
- {
- case item: ItemCandidateWithDetails =>
- item.candidate match {
- case _: BaseUserCandidate => 1L
- case _ => 0L
- }
- })
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala
deleted file mode 100644
index 1c3d2e817..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect.metrics
-
-import com.twitter.clientapp.thriftscala.LogEvent
-import com.twitter.logpipeline.client.common.EventPublisher
-import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect
-import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.EventNamespace
-import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.ClientEvent
-import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Config of a client event to be scribed under certain namespace.
- * @param eventNamespaceOverride overrides the default eventNamespace in the side effect.
- * Note that its fields (section/component/element/action) will
- * override the default namespace fields only if the fields are not
- * None. i.e. if you want to override the "section" field in the
- * default namespace with an empty section, you must specify
- * section = Some("")
- * in the override instead of
- * section = None
- *
- * @param metricFunction the function that extracts the metric value from a candidate.
- */
-case class EventConfig(
- eventNamespaceOverride: EventNamespace,
- metricFunction: CandidateMetricFunction)
-
-/**
- * Side effect to log client events server-side and to build metrics in the metric center.
- * By default will return "requests" event config.
- */
-class ScribeClientEventMetricsSideEffect[
- Query <: PipelineQuery,
- UnmarshalledResponseType <: HasMarshalling
-](
- override val identifier: SideEffectIdentifier,
- override val logPipelinePublisher: EventPublisher[LogEvent],
- override val page: String,
- defaultEventNamespace: EventNamespace,
- eventConfigs: Seq[EventConfig])
- extends ScribeClientEventSideEffect[Query, UnmarshalledResponseType] {
-
- override def buildClientEvents(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: UnmarshalledResponseType
- ): Seq[ScribeClientEventSideEffect.ClientEvent] = {
- // count the number of client events of type "requests"
- val requestClientEvent = ClientEvent(
- namespace = buildEventNamespace(EventNamespace(action = Some("requests")))
- )
-
- eventConfigs
- .map { config =>
- ClientEvent(
- namespace = buildEventNamespace(config.eventNamespaceOverride),
- eventValue = Some(selectedCandidates.map(config.metricFunction(_)).sum))
- }
- // scribe client event only when the metric sum is non-zero
- .filter(clientEvent => clientEvent.eventValue.exists(_ > 0L)) :+ requestClientEvent
- }
-
- private def buildEventNamespace(eventNamespaceOverride: EventNamespace): EventNamespace =
- EventNamespace(
- section = eventNamespaceOverride.section.orElse(defaultEventNamespace.section),
- component = eventNamespaceOverride.component.orElse(defaultEventNamespace.component),
- element = eventNamespaceOverride.element.orElse(defaultEventNamespace.element),
- action = eventNamespaceOverride.action.orElse(defaultEventNamespace.action)
- )
-}
diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala
deleted file mode 100644
index ae3c69353..000000000
--- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.twitter.product_mixer.component_library.side_effect.metrics
-
-import com.twitter.clientapp.thriftscala.LogEvent
-import com.twitter.logpipeline.client.common.EventPublisher
-import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.EventNamespace
-import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Build [[ScribeClientEventMetricsSideEffect]] with extra [[EventConfig]]
- */
-case class ScribeClientEventMetricsSideEffectBuilder(
- eventConfigs: Seq[EventConfig] = Seq.empty) {
-
- /**
- * Append extra [[EventConfig]] to [[ScribeClientEventMetricsSideEffectBuilder]]
- */
- def withEventConfig(
- eventConfig: EventConfig
- ): ScribeClientEventMetricsSideEffectBuilder =
- this.copy(eventConfigs = this.eventConfigs :+ eventConfig)
-
- /**
- * Build [[EventConfig]] with customized [[EventNamespace]] and customized [[CandidateMetricFunction]]
- * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]]
- * @param metricFunction [[CandidateMetricFunction]]
- */
- def withEventConfig(
- eventNamespaceOverride: EventNamespace,
- metricFunction: CandidateMetricFunction
- ): ScribeClientEventMetricsSideEffectBuilder =
- withEventConfig(EventConfig(eventNamespaceOverride, metricFunction))
-
- /**
- * Log served tweets events server side and build metrics in the metric center.
- * Default event name space action is "served_tweets", default metric function is [[DefaultServedTweetsSumFunction]]
- * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]]
- * @param metricFunction [[CandidateMetricFunction]]
- */
- def withServedTweets(
- eventNamespaceOverride: EventNamespace = EventNamespace(action = Some("served_tweets")),
- metricFunction: CandidateMetricFunction = DefaultServedTweetsSumFunction
- ): ScribeClientEventMetricsSideEffectBuilder = withEventConfig(
- eventNamespaceOverride = eventNamespaceOverride,
- metricFunction = metricFunction)
-
- /**
- * Log served users events server side and build metrics in the metric center.
- * Default event name space action is "served_users", default metric function is [[DefaultServedUsersSumFunction]]
- * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]]
- * @param metricFunction [[CandidateMetricFunction]]
- */
- def withServedUsers(
- eventNamespaceOverride: EventNamespace = EventNamespace(action = Some("served_users")),
- metricFunction: CandidateMetricFunction = DefaultServedUsersSumFunction
- ): ScribeClientEventMetricsSideEffectBuilder = withEventConfig(
- eventNamespaceOverride = eventNamespaceOverride,
- metricFunction = metricFunction)
-
- /**
- * Build [[ScribeClientEventMetricsSideEffect]]
- * @param identifier unique identifier of the side effect
- * @param defaultEventNamespace default event namespace to log
- * @param logPipelinePublisher [[EventPublisher]] to publish events
- * @param page The page which will be defined in the namespace. This is typically the service name that's scribing
- * @tparam Query [[PipelineQuery]]
- * @tparam UnmarshalledResponseType [[HasMarshalling]]
- * @return [[ScribeClientEventMetricsSideEffect]]
- */
- def build[Query <: PipelineQuery, UnmarshalledResponseType <: HasMarshalling](
- identifier: SideEffectIdentifier,
- defaultEventNamespace: EventNamespace,
- logPipelinePublisher: EventPublisher[LogEvent],
- page: String
- ): ScribeClientEventMetricsSideEffect[Query, UnmarshalledResponseType] = {
- new ScribeClientEventMetricsSideEffect[Query, UnmarshalledResponseType](
- identifier = identifier,
- logPipelinePublisher = logPipelinePublisher,
- defaultEventNamespace = defaultEventNamespace,
- page = page,
- eventConfigs = eventConfigs)
- }
-}
diff --git a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD b/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD
deleted file mode 100644
index d6cf0b82c..000000000
--- a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD
+++ /dev/null
@@ -1,8 +0,0 @@
-java_library(
- sources = ["*.java"],
- platform = "java8",
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- ],
-)
diff --git a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java b/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java
deleted file mode 100644
index dffc5cd7f..000000000
--- a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.product.guice.scope;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-import java.lang.annotation.Retention;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import java.lang.annotation.Target;
-
-import com.google.inject.ScopeAnnotation;
-
-@Target({ TYPE, METHOD })
-@Retention(RUNTIME)
-@ScopeAnnotation
-public @interface ProductScoped {}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala
deleted file mode 100644
index 05240a66a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.common.alert.NotificationGroup
-import com.twitter.product_mixer.core.functional_component.common.alert.Source
-
-/**
- * Simple representation for an [[Alert]] used for Product Mixer's JSON API, which in turn is
- * consumed by our monitoring script generation job and Turntable.
- *
- * @note not all mixers will upgrade at the same time so new fields should be added with backwards
- * compatibility in mind.
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-private[core] case class AlertConfig(
- source: Source,
- metricType: String,
- notificationGroup: NotificationGroup,
- warnPredicate: PredicateConfig,
- criticalPredicate: PredicateConfig,
- runbookLink: Option[String],
- metricSuffix: Option[String])
-
-private[core] object AlertConfig {
-
- /** Represent this [[Alert]] as an [[AlertConfig]] case class */
- private[core] def apply(alert: Alert): AlertConfig =
- AlertConfig(
- alert.source,
- alert.alertType.metricType,
- alert.notificationGroup,
- PredicateConfig(alert.warnPredicate),
- PredicateConfig(alert.criticalPredicate),
- alert.runbookLink,
- alert.metricSuffix
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD
deleted file mode 100644
index 879a1f49d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD
+++ /dev/null
@@ -1,39 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/twitter/bijection:core",
- "3rdparty/jvm/javax/inject:javax.inject",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/http-server/src/main/scala/com/twitter/finatra/http",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry",
- "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema",
- "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/json",
- "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/scrooge/scala",
- "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/serialization/thrift",
- "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/tree",
- "scrooge/scrooge-core/src/main/scala",
- "scrooge/scrooge-generator/src/main/scala",
- "scrooge/scrooge-serializer",
- "src/thrift/com/twitter/context:twitter-context-scala",
- "src/thrift/com/twitter/scrooge_internal/schema:thrift-scala",
- "twitter-context/src/main/scala",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "src/thrift/com/twitter/context:twitter-context-scala",
- "twitter-context/src/main/scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala
deleted file mode 100644
index 29d1a904c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.twitter.context.TwitterContext
-import com.twitter.context.thriftscala.Viewer
-import com.twitter.product_mixer.TwitterContextPermit
-import com.twitter.product_mixer.core.model.marshalling.request.ClientContext
-
-/**
- * Mixes in support to forge the UserIds in TwitterContext for debug purposes.
- *
- * A thrift controller can extend DebugTwitterContext and wrap it's execution logic:
- *
- * {{{
- * withDebugTwitterContext(request.clientContext) {
- * Stitch.run(...)
- * }
- * }}}
- */
-trait DebugTwitterContext {
-
- private val ctx = TwitterContext(TwitterContextPermit)
-
- /**
- * Wrap some function in a debug TwitterContext with hardcoded userIds
- * to the ClientContext.userId.
- *
- * @param clientContext - A product mixer request client context
- * @param f The function to wrap
- */
- def withDebugTwitterContext[T](clientContext: ClientContext)(f: => T): T = {
- ctx.let(
- forgeTwitterContext(
- clientContext.userId
- .getOrElse(throw new IllegalArgumentException("missing required field: user id")))
- )(f)
- }
-
- // Generate a fake Twitter Context for debug usage.
- // Generally the TwitterContext is created by the API service, and Strato uses it for permission control.
- // When we use our debug endpoint, we instead create our own context so that Strato finds something useful.
- // We enforce ACLs directly via Thrift Web Forms' permission system.
- private def forgeTwitterContext(userId: Long): Viewer = {
- Viewer(
- auditIp = None,
- ipTags = Set.empty,
- userId = Some(userId),
- guestId = None,
- clientApplicationId = None,
- userAgent = None,
- locationToken = None,
- authenticatedUserId = Some(userId),
- guestToken = None
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala
deleted file mode 100644
index 543888093..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.twitter.finagle.http.Request
-import com.twitter.inject.Injector
-import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy
-import com.twitter.product_mixer.core.functional_component.common.access_policy.WithDebugAccessPolicies
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineConfig
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineConfig
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineConfig
-import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig
-import com.twitter.product_mixer.core.service.component_registry
-import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry
-import com.twitter.product_mixer.core.service.component_registry.ComponentRegistrySnapshot
-import com.twitter.util.Future
-
-case class GetComponentRegistryHandler(injector: Injector) {
- lazy val componentRegistry: ComponentRegistry = injector.instance[ComponentRegistry]
-
- def apply(request: Request): Future[ComponentRegistryResponse] = {
- componentRegistry.get.map { currentComponentRegistry: ComponentRegistrySnapshot =>
- val registeredComponents = currentComponentRegistry.getAllRegisteredComponents.map {
- registeredComponent =>
- val componentIdentifier = registeredComponent.identifier
- val childComponents = currentComponentRegistry
- .getChildComponents(componentIdentifier)
- .map { childComponent =>
- ChildComponent(
- componentType = childComponent.componentType,
- name = childComponent.name,
- relativeScopes = componentIdentifier.toScopes ++ childComponent.toScopes,
- qualityFactorMonitoringConfig =
- buildQualityFactoringMonitoringConfig(registeredComponent, childComponent)
- )
- }
-
- RegisteredComponent(
- componentType = componentIdentifier.componentType,
- name = componentIdentifier.name,
- scopes = componentIdentifier.toScopes,
- children = childComponents,
- alertConfig = Some(registeredComponent.component.alerts.map(AlertConfig.apply)),
- sourceFile = Some(registeredComponent.sourceFile),
- debugAccessPolicies = Some(registeredComponent.component match {
- case withDebugAccessPolicies: WithDebugAccessPolicies =>
- withDebugAccessPolicies.debugAccessPolicies
- case _ => Set.empty
- })
- )
- }
-
- ComponentRegistryResponse(registeredComponents)
- }
- }
-
- private def buildQualityFactoringMonitoringConfig(
- parent: component_registry.RegisteredComponent,
- child: ComponentIdentifier
- ): Option[QualityFactorMonitoringConfig] = {
- val qualityFactorConfigs: Option[Map[ComponentIdentifier, QualityFactorConfig]] =
- parent.component match {
- case pipeline: Pipeline[_, _] =>
- pipeline.config match {
- case config: RecommendationPipelineConfig[_, _, _, _] =>
- Some(config.qualityFactorConfigs)
- case config: MixerPipelineConfig[_, _, _] =>
- Some(
- config.qualityFactorConfigs
- .asInstanceOf[Map[ComponentIdentifier, QualityFactorConfig]])
- case config: ProductPipelineConfig[_, _, _] =>
- Some(config.qualityFactorConfigs)
- case _ => None
- }
- case _ => None
- }
-
- val qfConfigForChild: Option[QualityFactorConfig] = qualityFactorConfigs.flatMap(_.get(child))
-
- qfConfigForChild.map { qfConfig =>
- QualityFactorMonitoringConfig(
- boundMin = qfConfig.qualityFactorBounds.bounds.minInclusive,
- boundMax = qfConfig.qualityFactorBounds.bounds.maxInclusive
- )
- }
- }
-}
-
-case class RegisteredComponent(
- componentType: String,
- name: String,
- scopes: Seq[String],
- children: Seq[ChildComponent],
- alertConfig: Option[Seq[AlertConfig]],
- sourceFile: Option[String],
- debugAccessPolicies: Option[Set[AccessPolicy]])
-
-case class ChildComponent(
- componentType: String,
- name: String,
- relativeScopes: Seq[String],
- qualityFactorMonitoringConfig: Option[QualityFactorMonitoringConfig])
-
-/**
- * The shape of the data returned to callers after hitting the `component-registry` endpoint
- *
- * @note changes to [[ComponentRegistryResponse]] or contained types should be reflected
- * in dashboard generation code in the `monitoring-configs/product_mixer` directory.
- */
-case class ComponentRegistryResponse(
- registeredComponents: Seq[RegisteredComponent])
-
-case class ProductPipeline(identifier: String)
-case class ProductPipelinesResponse(productPipelines: Seq[ProductPipeline])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala
deleted file mode 100644
index 7814100dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.twitter.finagle.http.Request
-import com.twitter.scrooge.BinaryThriftStructSerializer
-import com.twitter.scrooge.ThriftMethod
-import com.twitter.scrooge.schema.ThriftDefinitions
-import com.twitter.scrooge.schema.scrooge.scala.CompiledScroogeDefBuilder
-import com.twitter.scrooge.schema.serialization.thrift.ReferenceResolver
-import com.twitter.scrooge.schema.serialization.thrift.ThriftDefinitionsSerializer
-import com.twitter.scrooge.schema.{thriftscala => THRIFT}
-
-/**
- * Endpoint to expose a Mixer's expected query configuration, including the request schema.
- *
- * @param debugEndpoint the debug Thrift endpoint. Passing [[None]] disables the query debugging
- * feature.
- * @tparam ServiceIface a thrift service containing the [[debugEndpoint]]
- */
-case class GetDebugConfigurationHandler[ServiceIface](
- thriftMethod: ThriftMethod
-)(
- implicit val serviceIFace: Manifest[ServiceIface]) {
-
- // We need to binary encode the service def because the underlying Thrift isn't sufficiently
- // annotated to be serialized/deserialized by Jackson
- private val serviceDef = {
- val fullServiceDefinition: ThriftDefinitions.ServiceDef = CompiledScroogeDefBuilder
- .build(serviceIFace).asInstanceOf[ThriftDefinitions.ServiceDef]
-
- val endpointDefinition: ThriftDefinitions.ServiceEndpointDef =
- fullServiceDefinition.endpointsByName(thriftMethod.name)
-
- // Create a service definition which just contains the debug endpoint. At a bare minimum, we need
- // to give callers a way to identify the debug endpoint. Sending back all the endpoints is
- // redundant.
- val serviceDefinition: ThriftDefinitions.ServiceDef =
- fullServiceDefinition.copy(endpoints = Seq(endpointDefinition))
-
- val thriftDefinitionsSerializer = {
- // We don't make use of references but a reference resolver is required by the Scrooge API
- val noopReferenceResolver: ReferenceResolver =
- (_: THRIFT.ReferenceDef) => throw new Exception("no references")
-
- new ThriftDefinitionsSerializer(noopReferenceResolver, enableReferences = false)
- }
-
- val thriftBinarySerializer = BinaryThriftStructSerializer.apply(THRIFT.Definition)
-
- val serializedServiceDef = thriftDefinitionsSerializer(serviceDefinition)
-
- thriftBinarySerializer.toBytes(serializedServiceDef)
- }
-
- def apply(request: Request): DebugConfigurationResponse =
- DebugConfigurationResponse(thriftMethod.name, serviceDef)
-}
-
-case class DebugConfigurationResponse(
- debugEndpointName: String,
- serviceDefinition: Array[Byte])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala
deleted file mode 100644
index c2f217400..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate
-
-/** Simple representation for a [[Predicate]] used for dashboard generation */
-private[core] case class PredicateConfig(
- operator: String,
- threshold: Double,
- datapointsPastThreshold: Int,
- duration: Int,
- metricGranularity: String)
-
-private[core] object PredicateConfig {
-
- /** Convert this [[Predicate]] into a [[PredicateConfig]] */
- def apply(predicate: Predicate): PredicateConfig = PredicateConfig(
- predicate.operator.toString,
- predicate.threshold,
- predicate.datapointsPastThreshold,
- predicate.duration,
- predicate.metricGranularity.unit)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala
deleted file mode 100644
index e7f761825..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-import com.twitter.finagle.http.Request
-import com.twitter.finagle.http.Response
-import com.twitter.finagle.http.Status
-import com.twitter.finagle.http.RouteIndex
-import com.twitter.finatra.http.Controller
-import com.twitter.scrooge.ThriftMethod
-import com.twitter.inject.Injector
-import com.twitter.inject.annotations.Flags
-import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry
-import com.twitter.product_mixer.core.service.component_registry.{
- RegisteredComponent => ComponentRegistryRegisteredComponent
-}
-import com.twitter.util.Future
-import java.net.URLEncoder
-
-/**
- * Register endpoints necessary for enabling Product Mixer tooling such as alerts, dashboard
- * generation and Turntable.
- *
- * @param debugEndpoint a debug endpoint to run queries against. This feature is experimental and we
- * do not recommend that teams use it yet. Providing [[None]] will disable
- * debug queries.
- * @tparam ServiceIface a thrift service containing the [[debugEndpoint]]
- */
-case class ProductMixerController[ServiceIface](
- injector: Injector,
- debugEndpoint: ThriftMethod,
-)(
- implicit val serviceIFace: Manifest[ServiceIface])
- extends Controller {
-
- val isLocal: Boolean = injector.instance[Boolean](Flags.named(ServiceLocal))
-
- if (!isLocal) {
- prefix("/admin/product-mixer") {
- val productNamesFut: Future[Seq[String]] =
- injector.instance[ComponentRegistry].get.map { componentRegistry =>
- componentRegistry.getAllRegisteredComponents.collect {
- case ComponentRegistryRegisteredComponent(identifier: ProductIdentifier, _, _) =>
- identifier.name
- }
- }
-
- productNamesFut.map { productNames =>
- productNames.foreach { productName =>
- get(
- route = "/debug-query/" + productName,
- admin = true,
- index = Some(RouteIndex(alias = "Query " + productName, group = "Feeds/Debug Query"))
- ) { _: Request =>
- val auroraPath =
- URLEncoder.encode(System.getProperty("aurora.instanceKey", ""), "UTF-8")
-
- // Extract service name from clientId since there isn't a specific flag for that
- val serviceName = injector
- .instance[String](Flags.named("thrift.clientId"))
- .split("\\.")(0)
-
- val redirectUrl =
- s"https://feeds.twitter.biz/dtab/$serviceName/$productName?servicePath=$auroraPath"
-
- val response = Response().status(Status.Found)
- response.location = redirectUrl
- response
- }
- }
- }
- }
- }
-
- prefix("/product-mixer") {
- get(route = "/component-registry")(GetComponentRegistryHandler(injector).apply)
- get(route = "/debug-configuration")(GetDebugConfigurationHandler(debugEndpoint).apply)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala
deleted file mode 100644
index 12bbe4850..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.controllers
-
-// Bounds here are inclusive
-case class QualityFactorMonitoringConfig(
- boundMin: Double,
- boundMax: Double)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD
deleted file mode 100644
index cd054940f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD
+++ /dev/null
@@ -1,10 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "util/util-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala
deleted file mode 100644
index 820abe25c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.core.feature
-
-/**
- * A [[Feature]] is a single measurable or computable property of an entity.
- *
- * @note If a [[Feature]] is optional then the [[Value]] should be `Option[Value]`
- *
- * @note If a [[Feature]] is populated with a [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]]
- * and the hydration fails, a failure will be stored for the [[Feature]].
- * If that [[Feature]] is accessed with [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get]]
- * then the stored exception will be thrown, essentially failing-closed.
- * You can use [[FeatureWithDefaultOnFailure]] or [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse]]
- * instead to avoid these issues and instead fail-open.
- * If correctly hydrating a Feature's value is essential to the request being correct,
- * then you should fail-closed on failure to hydrate it by extending [[Feature]] directly.
- *
- * This does not apply to [[Feature]]s from [[com.twitter.product_mixer.core.functional_component.transformer.FeatureTransformer]]
- * which throw in the calling Pipeline instead of storing their failures.
- *
- * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet,
- * Query, etc.
- * @tparam Value The type of the value of this feature.
- */
-trait Feature[-Entity, Value] { self =>
- override def toString: String = {
- Feature.getSimpleName(self.getClass)
- }
-}
-
-/**
- * With a [[Feature]], if the [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] fails,
- * the failure will be caught by the platform and stored in the [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]].
- * Accessing a failed feature via [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get()]]
- * will throw the exception that was caught while attempting to hydrate the feature. If there's a
- * reasonable default for a [[Feature]] to fail-open with, then throwing the exception at read time
- * can be prevented by defining a `defaultValue` via [[FeatureWithDefaultOnFailure]]. When accessing
- * a failed feature via [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get()]]
- * for a [[FeatureWithDefaultOnFailure]], the `defaultValue` will be returned.
- *
- *
- * @note [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse()]] can also be used
- * to access a failed feature without throwing the exception, by defining the default via the
- * [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse()]] method call
- * instead of as part of the feature declaration.
- * @note This does not apply to [[FeatureWithDefaultOnFailure]]s from [[com.twitter.product_mixer.core.functional_component.transformer.FeatureTransformer]]
- * which throw in the calling Pipeline instead of storing their failures.
- *
- * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet,
- * Query, etc.
- * @tparam Value The type of the value of this feature.
- */
-trait FeatureWithDefaultOnFailure[Entity, Value] extends Feature[Entity, Value] {
-
- /** The default value a feature should return should it fail to be hydrated */
- def defaultValue: Value
-}
-
-trait ModelFeatureName { self: Feature[_, _] =>
- def featureName: String
-}
-
-object Feature {
-
- /**
- * Avoid `malformed class name` exceptions due to the presence of the `$` character
- * Also strip off trailing $ signs for readability
- */
- def getSimpleName[T](c: Class[T]): String = {
- c.getName.stripSuffix("$").lastIndexOf("$") match {
- case -1 => c.getSimpleName.stripSuffix("$")
- case index => c.getName.substring(index + 1).stripSuffix("$")
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD
deleted file mode 100644
index c94c4bec6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "src/java/com/twitter/ml/api:api-base",
- "src/scala/com/twitter/ml/api/util:datarecord",
- "src/thrift/com/twitter/dal/personal_data:personal_data-java",
- "src/thrift/com/twitter/ml/api:data-java",
- "src/thrift/com/twitter/ml/api:data-scala",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "src/thrift/com/twitter/dal/personal_data:personal_data-java",
- "src/thrift/com/twitter/ml/api:data-java",
- "src/thrift/com/twitter/ml/api:data-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala
deleted file mode 100644
index 1a69e9a7f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala
+++ /dev/null
@@ -1,316 +0,0 @@
-package com.twitter.product_mixer.core.feature.datarecord
-
-import com.twitter.dal.personal_data.thriftjava.PersonalDataType
-import com.twitter.ml.api.Feature
-import com.twitter.ml.api.DataType
-import com.twitter.ml.api.thriftscala.GeneralTensor
-import com.twitter.ml.api.thriftscala.StringTensor
-import com.twitter.ml.api.util.ScalaToJavaDataRecordConversions
-import com.twitter.ml.api.{GeneralTensor => JGeneralTensor}
-import com.twitter.ml.api.{RawTypedTensor => JRawTypedTensor}
-import com.twitter.ml.api.{Feature => MlFeature}
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
-import java.util.{Map => JMap}
-import java.util.{Set => JSet}
-import java.lang.{Long => JLong}
-import java.lang.{Boolean => JBoolean}
-import java.lang.{Double => JDouble}
-import scala.collection.JavaConverters._
-
-/**
- * Defines a conversion function for customers to mix-in when constructing a DataRecord supported
- * feature. We do this because the ML Feature representation is written in Java and uses Java types.
- * Furthermore, allowing customers to construct their own ML Feature directly can leave room
- * for mistyping errors, such as using a Double ML Feature on a String Product Mixer feature.
- * This mix in enforces that the customer only uses the right types, while making it easier
- * to setup a DataRecord Feature with nothing but a feature name and personal data types.
- * @tparam FeatureValueType The type of the underlying Product Mixer feature value.
- */
-sealed trait DataRecordCompatible[FeatureValueType] {
- // The feature value type in ProMix.
- final type FeatureType = FeatureValueType
- // The underlying DataRecord value type, sometimes this differs from the Feature Store and ProMix type.
- type DataRecordType
-
- def featureName: String
- def personalDataTypes: Set[PersonalDataType]
-
- private[product_mixer] def mlFeature: MlFeature[DataRecordType]
-
- /**
- * To & from Data Record value converters. In most cases, this is one to one when the types match
- * but in some cases, certain features are modeled as different types in Data Record. For example,
- * some features that are Long (e.g, such as TweepCred) are sometimes stored as Doubles.
- */
- private[product_mixer] def toDataRecordFeatureValue(featureValue: FeatureType): DataRecordType
- private[product_mixer] def fromDataRecordFeatureValue(featureValue: DataRecordType): FeatureType
-
-}
-
-/**
- * Converter for going from String feature value to String ML Feature.
- */
-trait StringDataRecordCompatible extends DataRecordCompatible[String] {
- override type DataRecordType = String
-
- final override lazy val mlFeature: MlFeature[String] =
- new MlFeature.Text(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: String
- ): String = featureValue
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: String
- ): String = featureValue
-}
-
-/**
- * Converter for going from Long feature value to Discrete/Long ML Feature.
- */
-trait LongDiscreteDataRecordCompatible extends DataRecordCompatible[Long] {
- override type DataRecordType = JLong
-
- final override lazy val mlFeature: MlFeature[JLong] =
- new Feature.Discrete(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JLong
- ): Long = featureValue
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Long
- ): JLong = featureValue
-}
-
-/**
- * Converter for going from Long feature value to Continuous/Double ML Feature.
- */
-trait LongContinuousDataRecordCompatible extends DataRecordCompatible[Long] {
- override type DataRecordType = JDouble
-
- final override lazy val mlFeature: MlFeature[JDouble] =
- new Feature.Continuous(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: FeatureType
- ): JDouble = featureValue.toDouble
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JDouble
- ): Long = featureValue.longValue()
-}
-
-/**
- * Converter for going from an Integer feature value to Long/Discrete ML Feature.
- */
-trait IntDiscreteDataRecordCompatible extends DataRecordCompatible[Int] {
- override type DataRecordType = JLong
-
- final override lazy val mlFeature: MlFeature[JLong] =
- new MlFeature.Discrete(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JLong
- ): Int = featureValue.toInt
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Int
- ): JLong = featureValue.toLong
-}
-
-/**
- * Converter for going from Integer feature value to Continuous/Double ML Feature.
- */
-trait IntContinuousDataRecordCompatible extends DataRecordCompatible[Int] {
- override type DataRecordType = JDouble
-
- final override lazy val mlFeature: MlFeature[JDouble] =
- new Feature.Continuous(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Int
- ): JDouble = featureValue.toDouble
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JDouble
- ): Int = featureValue.toInt
-}
-
-/**
- * Converter for going from Double feature value to Continuous/Double ML Feature.
- */
-trait DoubleDataRecordCompatible extends DataRecordCompatible[Double] {
- override type DataRecordType = JDouble
-
- final override lazy val mlFeature: MlFeature[JDouble] =
- new MlFeature.Continuous(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JDouble
- ): Double = featureValue
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Double
- ): JDouble = featureValue
-}
-
-/**
- * Converter for going from Boolean feature value to Boolean ML Feature.
- */
-trait BoolDataRecordCompatible extends DataRecordCompatible[Boolean] {
- override type DataRecordType = JBoolean
-
- final override lazy val mlFeature: MlFeature[JBoolean] =
- new MlFeature.Binary(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JBoolean
- ): Boolean = featureValue
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Boolean
- ): JBoolean = featureValue
-}
-
-/**
- * Converter for going from a ByteBuffer feature value to ByteBuffer ML Feature.
- */
-trait BlobDataRecordCompatible extends DataRecordCompatible[ByteBuffer] {
- override type DataRecordType = ByteBuffer
-
- final override lazy val mlFeature: MlFeature[ByteBuffer] =
- new Feature.Blob(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: ByteBuffer
- ): ByteBuffer = featureValue
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: ByteBuffer
- ): ByteBuffer = featureValue
-}
-
-/**
- * Converter for going from a Map[String, Double] feature value to Sparse Double/Continious ML Feature.
- */
-trait SparseContinuousDataRecordCompatible extends DataRecordCompatible[Map[String, Double]] {
- override type DataRecordType = JMap[String, JDouble]
-
- final override lazy val mlFeature: MlFeature[JMap[String, JDouble]] =
- new Feature.SparseContinuous(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: Map[String, Double]
- ): JMap[String, JDouble] =
- featureValue.mapValues(_.asInstanceOf[JDouble]).asJava
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JMap[String, JDouble]
- ) = featureValue.asScala.toMap.mapValues(_.doubleValue())
-}
-
-/**
- * Converter for going from a Set[String] feature value to SparseBinary/String Set ML Feature.
- */
-trait SparseBinaryDataRecordCompatible extends DataRecordCompatible[Set[String]] {
- override type DataRecordType = JSet[String]
-
- final override lazy val mlFeature: MlFeature[JSet[String]] =
- new Feature.SparseBinary(featureName, personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JSet[String]
- ) = featureValue.asScala.toSet
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: FeatureType
- ): JSet[String] = featureValue.asJava
-}
-
-/**
- * Marker trait for any feature value to Tensor ML Feature. Not directly usable.
- */
-sealed trait TensorDataRecordCompatible[FeatureV] extends DataRecordCompatible[FeatureV] {
- override type DataRecordType = JGeneralTensor
- override def mlFeature: MlFeature[JGeneralTensor]
-}
-
-/**
- * Converter for a double to a Tensor feature encoded as float encoded RawTypedTensor
- */
-trait RawTensorFloatDoubleDataRecordCompatible extends TensorDataRecordCompatible[Double] {
- final override lazy val mlFeature: MlFeature[JGeneralTensor] =
- new Feature.Tensor(
- featureName,
- DataType.FLOAT,
- List.empty[JLong].asJava,
- personalDataTypes.asJava)
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: FeatureType
- ) = {
- val byteBuffer: ByteBuffer =
- ByteBuffer
- .allocate(4).order(ByteOrder.LITTLE_ENDIAN).putFloat(featureValue.toFloat)
- byteBuffer.flip()
- val tensor = new JGeneralTensor()
- tensor.setRawTypedTensor(new JRawTypedTensor(DataType.FLOAT, byteBuffer))
- tensor
- }
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JGeneralTensor
- ) = {
- val tensor = Option(featureValue.getRawTypedTensor)
- .getOrElse(throw new UnexpectedTensorException(featureValue))
- tensor.content.order(ByteOrder.LITTLE_ENDIAN).getFloat().toDouble
- }
-}
-
-/**
- * Converter for a scala general tensor to java general tensor ML feature.
- */
-trait GeneralTensorDataRecordCompatible extends TensorDataRecordCompatible[GeneralTensor] {
-
- def dataType: DataType
- final override lazy val mlFeature: MlFeature[JGeneralTensor] =
- new Feature.Tensor(featureName, dataType, List.empty[JLong].asJava, personalDataTypes.asJava)
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: FeatureType
- ) = ScalaToJavaDataRecordConversions.scalaTensor2Java(featureValue)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JGeneralTensor
- ) = ScalaToJavaDataRecordConversions.javaTensor2Scala(featureValue)
-}
-
-/**
- * Converter for a scala string tensor to java general tensor ML feature.
- */
-trait StringTensorDataRecordCompatible extends TensorDataRecordCompatible[StringTensor] {
- final override lazy val mlFeature: MlFeature[JGeneralTensor] =
- new Feature.Tensor(
- featureName,
- DataType.STRING,
- List.empty[JLong].asJava,
- personalDataTypes.asJava)
-
- override private[product_mixer] def fromDataRecordFeatureValue(
- featureValue: JGeneralTensor
- ) = {
- ScalaToJavaDataRecordConversions.javaTensor2Scala(featureValue) match {
- case GeneralTensor.StringTensor(stringTensor) => stringTensor
- case _ => throw new UnexpectedTensorException(featureValue)
- }
- }
-
- override private[product_mixer] def toDataRecordFeatureValue(
- featureValue: FeatureType
- ) = ScalaToJavaDataRecordConversions.scalaTensor2Java(GeneralTensor.StringTensor(featureValue))
-}
-
-class UnexpectedTensorException(tensor: JGeneralTensor)
- extends Exception(s"Unexpected Tensor: $tensor")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala
deleted file mode 100644
index a718f9644..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.core.feature.datarecord
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.product_mixer.core.feature.Feature
-
-/**
- * A DataRecord supported feature mixin for enabling conversions from Product Mixer Features
- * to DataRecords. When using Feature Store features, this is pre-configured for the customer
- * under the hood. For non-Feature Store features, customers must mix in either [[DataRecordFeature]]
- * for required features, or [[DataRecordOptionalFeature]] for optional features, as well as mixing
- * in a corresponding [[DataRecordCompatible]] for their feature type.
- * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet,
- * Query, etc.
- * @tparam Value The type of the value of this feature.
- */
-sealed trait BaseDataRecordFeature[-Entity, Value] extends Feature[Entity, Value]
-
-private[product_mixer] abstract class FeatureStoreDataRecordFeature[-Entity, Value]
- extends BaseDataRecordFeature[Entity, Value]
-
-/**
- * Feature in a DataRecord for a required feature value; the corresponding feature will always be
- * available in the built DataRecord.
- */
-trait DataRecordFeature[-Entity, Value] extends BaseDataRecordFeature[Entity, Value] {
- self: DataRecordCompatible[Value] =>
-}
-
-/**
- * Feature in a DataRecord for an optional feature value; the corresponding feature will only
- * ever be set in a DataRecord if the value in the feature map is defined (Some(V)).
- */
-trait DataRecordOptionalFeature[-Entity, Value]
- extends BaseDataRecordFeature[Entity, Option[Value]] {
- self: DataRecordCompatible[Value] =>
-}
-
-/**
- * An entire DataRecord as a feature. This is useful when there is an existing DataRecord that
- * should be used as a whole instead of as individual [[DataRecordFeature]]s for example.
- */
-trait DataRecordInAFeature[-Entity] extends BaseDataRecordFeature[Entity, DataRecord]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD
deleted file mode 100644
index ea22972ca..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- "util/util-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala
deleted file mode 100644
index 870f8ad9f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala
+++ /dev/null
@@ -1,195 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.{
- FeatureStoreV1ResponseFeature => FSv1Feature
-}
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-
-/**
- * A set of features and their values. Associated with a specific instance of an Entity, though
- * that association is maintained by the framework.
- *
- * [[FeatureMapBuilder]] is used to build new FeatureMap instances
- */
-@JsonSerialize(using = classOf[FeatureMapSerializer])
-case class FeatureMap private[feature] (
- private[core] val underlyingMap: Map[Feature[_, _], Try[_]]) {
-
- /**
- * Returns the [[Value]] associated with the Feature
- *
- * If the Feature is missing from the feature map, it throws a [[MissingFeatureException]].
- * If the Feature failed and isn't a [[FeatureWithDefaultOnFailure]] this will throw the underlying exception
- * that the feature failed with during hydration.
- */
- def get[Value](feature: Feature[_, Value]): Value =
- getOrElse(feature, throw MissingFeatureException(feature), None)
-
- /**
- * Returns the [[Value]] associated with the Feature with the same semantics as
- * [[FeatureMap.get()]], but the underlying [[Try]] is returned to allow for checking the success
- * or error state of a feature hydration. This is helpful for implementing fall-back behavior in
- * case the feature is missing or hydration failed without a [[FeatureWithDefaultOnFailure]] set.
- *
- * @note The [[FeatureMap.getOrElse()]] logic is duplicated here to avoid unpacking and repacking
- * the [[Try]] that is already available in the [[underlyingMap]]
- */
- def getTry[Value](feature: Feature[_, Value]): Try[Value] =
- underlyingMap.get(feature) match {
- case None => Throw(MissingFeatureException(feature))
- case Some(value @ Return(_)) => value.asInstanceOf[Return[Value]]
- case Some(value @ Throw(_)) =>
- feature match {
- case f: FeatureWithDefaultOnFailure[_, Value] @unchecked => Return(f.defaultValue)
- case _ => value.asInstanceOf[Throw[Value]]
- }
- }
-
- /**
- * Returns the [[Value]] associated with the feature or a default if the key is not contained in the map
- * `default` can also be used to throw an exception.
- *
- * e.g. `.getOrElse(feature, throw new MyCustomException())`
- *
- * @note for [[FeatureWithDefaultOnFailure]], the [[FeatureWithDefaultOnFailure.defaultValue]]
- * will be returned if the [[Feature]] failed, but if it is missing/never hydrated,
- * then the `default` provided here will be used.
- */
- def getOrElse[Value](feature: Feature[_, Value], default: => Value): Value = {
- getOrElse(feature, default, Some(default))
- }
-
- /**
- * Private helper for getting features from the feature map, allowing us to define a default
- * when the feature is missing from the feature map, vs when its in the feature map but failed.
- * In the case of failed features, if the feature is a [FeatureWithDefaultOnFailure], it will
- * prioritize that default.
- * @param feature The feature to retrieve
- * @param missingDefault The default value to use when the feature is missing from the map.
- * @param failureDefault The default value to use when the feature is present but failed.
- * @tparam Value The value type of the feature.
- * @return The value stored in the map.
- */
- private def getOrElse[Value](
- feature: Feature[_, Value],
- missingDefault: => Value,
- failureDefault: => Option[Value]
- ): Value =
- underlyingMap.get(feature) match {
- case None => missingDefault
- case Some(Return(value)) => value.asInstanceOf[Value]
- case Some(Throw(err)) =>
- feature match {
- case f: FeatureWithDefaultOnFailure[_, Value] @unchecked => f.defaultValue
- case _ => failureDefault.getOrElse(throw err)
- }
- }
-
- /**
- * returns a new FeatureMap with
- * - the new Feature and Value pair if the Feature was not present
- * - overriding the previous Value if that Feature was previously present
- */
- def +[V](key: Feature[_, V], value: V): FeatureMap =
- new FeatureMap(underlyingMap + (key -> Return(value)))
-
- /**
- * returns a new FeatureMap with all the elements of current FeatureMap and `other`.
- *
- * @note if a [[Feature]] exists in both maps, the Value from `other` takes precedence
- */
- def ++(other: FeatureMap): FeatureMap = {
- if (other.isEmpty) {
- this
- } else if (isEmpty) {
- other
- } else if (this.getFeatures.contains(FSv1Feature) && other.getFeatures.contains(FSv1Feature)) {
- val mergedResponse =
- FeatureStoreV1Response.merge(this.get(FSv1Feature), other.get(FSv1Feature))
- val mergedResponseFeatureMap = FeatureMapBuilder().add(FSv1Feature, mergedResponse).build()
- new FeatureMap(underlyingMap ++ other.underlyingMap ++ mergedResponseFeatureMap.underlyingMap)
- } else {
- new FeatureMap(underlyingMap ++ other.underlyingMap)
- }
- }
-
- /** returns the keySet of Features in the map */
- def getFeatures: Set[Feature[_, _]] = underlyingMap.keySet
-
- /**
- * The Set of Features in the FeatureMap that have a successfully returned value. Failed features
- * will obviously not be here.
- */
- def getSuccessfulFeatures: Set[Feature[_, _]] = underlyingMap.collect {
- case (feature, Return(_)) => feature
- }.toSet
-
- def isEmpty: Boolean = underlyingMap.isEmpty
-
- override def toString: String = s"FeatureMap(${underlyingMap.toString})"
-}
-
-object FeatureMap {
- // Restrict access to the apply method.
- // This shouldn't be required after scala 2.13.2 (https://github.com/scala/scala/pull/7702)
- private[feature] def apply(underlyingMap: Map[Feature[_, _], Try[_]]): FeatureMap =
- FeatureMap(underlyingMap)
-
- /** Merges an arbitrary number of [[FeatureMap]]s from left-to-right */
- def merge(featureMaps: TraversableOnce[FeatureMap]): FeatureMap = {
- val builder = FeatureMapBuilder()
-
- /**
- * merge the current [[FSv1Feature]] with the existing accumulated one
- * and add the rest of the [[FeatureMap]]'s [[Feature]]s to the `builder`
- */
- def mergeInternal(
- featureMap: FeatureMap,
- accumulatedFsV1Response: Option[FeatureStoreV1Response]
- ): Option[FeatureStoreV1Response] = {
- if (featureMap.isEmpty) {
- accumulatedFsV1Response
- } else {
-
- val currentFsV1Response =
- if (featureMap.getFeatures.contains(FSv1Feature))
- Some(featureMap.get(FSv1Feature))
- else
- None
-
- val mergedFsV1Response = (accumulatedFsV1Response, currentFsV1Response) match {
- case (Some(merged), Some(current)) =>
- // both present so merge them
- Some(FeatureStoreV1Response.merge(merged, current))
- case (merged, current) =>
- // one or both are missing so use whichever is available
- merged.orElse(current)
- }
-
- featureMap.underlyingMap.foreach {
- case (FSv1Feature, _) => // FSv1Feature is only added once at the very end
- case (feature, value) => builder.addWithoutValidation(feature, value)
- }
- mergedFsV1Response
- }
- }
-
- featureMaps
- .foldLeft[Option[FeatureStoreV1Response]](None) {
- case (fsV1Response, featureMap) => mergeInternal(featureMap, fsV1Response)
- }.foreach(
- // add merged `FSv1Feature` to the `builder` at the end
- builder.add(FSv1Feature, _)
- )
-
- builder.build()
- }
-
- val empty = new FeatureMap(Map.empty)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala
deleted file mode 100644
index 91fe54d44..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-import scala.collection.mutable
-
-/**
- * [[FeatureMapBuilder]] is a typesafe way (it checks types vs the [[Feature]]s on `.add`) to build a [[FeatureMap]].
- *
- * Throws a [[DuplicateFeatureException]] if you try to add the same [[Feature]] more than once.
- *
- * These builders are __not__ reusable.
- */
-
-class FeatureMapBuilder {
- private val underlying = Map.newBuilder[Feature[_, _], Try[Any]]
- private val keys = mutable.HashSet.empty[Feature[_, _]]
- private var built = false
-
- /**
- * Add a [[Try]] of a [[Feature]] `value` to the map,
- * handling both the [[Return]] and [[Throw]] cases.
- *
- * Throws a [[DuplicateFeatureException]] if it's already present.
- *
- * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]`
- * but have an `Option[V]` you can use [[Try.orThrow]] to convert the [[Option]]
- * to a [[Try]], which will store the successful or failed [[Feature]] in the map.
- */
- def add[V](feature: Feature[_, V], value: Try[V]): FeatureMapBuilder = addTry(feature, value)
-
- /**
- * Add a successful [[Feature]] `value` to the map
- *
- * Throws a [[DuplicateFeatureException]] if it's already present.
- *
- * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]`
- * but have an `Option[V]` you can use [[Option.get]] or [[Option.getOrElse]]
- * to convert the [[Option]] to extract the underlying value,
- * which will throw immediately if it's [[None]] or add the successful [[Feature]] in the map.
- */
- def add[V](feature: Feature[_, V], value: V): FeatureMapBuilder =
- addTry(feature, Return(value))
-
- /**
- * Add a failed [[Feature]] `value` to the map
- *
- * Throws a [[DuplicateFeatureException]] if it's already present.
- */
- def addFailure(feature: Feature[_, _], throwable: Throwable): FeatureMapBuilder =
- addTry(feature, Throw(throwable))
-
- /**
- * [[add]] but for when the [[Feature]] types aren't known
- *
- * Add a [[Try]] of a [[Feature]] `value` to the map,
- * handling both the [[Return]] and [[Throw]] cases.
- *
- * Throws a [[DuplicateFeatureException]] if it's already present.
- *
- * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]`
- * but have an `Option[V]` you can use [[Try.orThrow]] to convert the [[Option]]
- * to a [[Try]], which will store the successful or failed [[Feature]] in the map.
- */
- def addTry(feature: Feature[_, _], value: Try[_]): FeatureMapBuilder = {
- if (keys.contains(feature)) {
- throw new DuplicateFeatureException(feature)
- }
- addWithoutValidation(feature, value)
- }
-
- /**
- * [[addTry]] but without a [[DuplicateFeatureException]] check
- *
- * @note Only for use internally within [[FeatureMap.merge]]
- */
- private[featuremap] def addWithoutValidation(
- feature: Feature[_, _],
- value: Try[_]
- ): FeatureMapBuilder = {
- keys += feature
- underlying += ((feature, value))
- this
- }
-
- /** Builds the FeatureMap */
- def build(): FeatureMap = {
- if (built) {
- throw ReusedFeatureMapBuilderException
- }
-
- built = true
- new FeatureMap(underlying.result())
- }
-}
-
-object FeatureMapBuilder {
-
- /** Returns a new [[FeatureMapBuilder]] for making [[FeatureMap]]s */
- def apply(): FeatureMapBuilder = new FeatureMapBuilder
-}
-
-class DuplicateFeatureException(feature: Feature[_, _])
- extends UnsupportedOperationException(s"Feature $feature already exists in FeatureMap")
-
-object ReusedFeatureMapBuilderException
- extends UnsupportedOperationException(
- "build() cannot be called more than once since FeatureMapBuilders are not reusable")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala
deleted file mode 100644
index bbd57cfb6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap
-
-import com.twitter.product_mixer.core.feature.Feature
-
-case class MissingFeatureException(feature: Feature[_, _])
- extends Exception("Missing value for " + feature) {
- override def toString: String = getMessage
-}
-
-class InvalidPredictionRecordMergeException
- extends Exception(
- "Use FeatureMap.plusPlusOptimized instead of FeatureMap.++ when the FeatureMaps on both sides of the merge contain PredictionRecords")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala
deleted file mode 100644
index 746f178fb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-import com.twitter.util.Return
-
-/**
- * Rendering feature maps is dangerous because we don't control all the data that's stored in them.
- * This can result failed requests, as we might try to render a recursive structure, very large
- * structure, etc. Create a simple map using toString, this mostly works and is better than failing
- * the request.
- *
- * @note changes to serialization logic can have serious performance implications given how hot the
- * serialization path is. Consider benchmarking changes with [[com.twitter.product_mixer.core.benchmark.CandidatePipelineResultSerializationBenchmark]]
- */
-private[featuremap] class FeatureMapSerializer() extends JsonSerializer[FeatureMap] {
- override def serialize(
- featureMap: FeatureMap,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit = {
- gen.writeStartObject()
-
- featureMap.underlyingMap.foreach {
- case (FeatureStoreV1ResponseFeature, Return(value)) =>
- // We know that value has to be [[FeatureStoreV1Response]] but its type has been erased,
- // preventing us from pattern-matching.
- val featureStoreResponse = value.asInstanceOf[FeatureStoreV1Response]
-
- val featuresIterator = featureStoreResponse.richDataRecord.allFeaturesIterator()
- while (featuresIterator.moveNext()) {
- gen.writeStringField(
- featuresIterator.getFeature.getFeatureName,
- s"${featuresIterator.getFeatureType.name}(${truncateString(
- featuresIterator.getFeatureValue.toString)})")
- }
-
- featureStoreResponse.failedFeatures.foreach {
- case (failedFeature, failureReasons) =>
- gen.writeStringField(
- failedFeature.toString,
- s"Failed(${truncateString(failureReasons.toString)})")
- }
- case (name, Return(value)) =>
- gen.writeStringField(name.toString, truncateString(value.toString))
- case (name, error) =>
- // Note: we don't match on Throw(error) because we want to keep it for the toString
- gen.writeStringField(name.toString, truncateString(error.toString))
-
- }
-
- gen.writeEndObject()
- }
-
- // Some features can be very large when stringified, for example when a dependant candidate
- // pipeline is used, the entire previous candidate pipeline result is serialized into a feature.
- // This causes significant performance issues when the result is later sent over the wire.
- private def truncateString(input: String): String =
- if (input.length > 1000) input.take(1000) + "..." else input
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala
deleted file mode 100644
index 49d2d44eb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.stitch.Stitch
-
-import scala.collection.immutable.Queue
-
-/**
- * An internal representation of an async [[FeatureMap]] containing [[Stitch]]s of [[FeatureMap]]s
- * which are already running in the background.
- *
- * Async features are added by providing the [[PipelineStepIdentifier]] of the [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step Step]]
- * before which the async [[Feature]]s are needed, and a [[Stitch]] of the async [[FeatureMap]].
- * It's expected that the [[Stitch]] has already been started and is running in the background.
- *
- * While not essential to it's core behavior, [[AsyncFeatureMap]] also keeps track of the [[FeatureHydratorIdentifier]]
- * and the Set of [[Feature]]s which will be hydrated for each [[Stitch]] of a [[FeatureMap]] it's given.
- *
- * @param asyncFeatureMaps the [[FeatureMap]]s for [[PipelineStepIdentifier]]s which have not been reached yet
- *
- * @note [[PipelineStepIdentifier]]s must only refer to [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step Step]]s
- * in the current [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]].
- * Only plain [[FeatureMap]]s are passed into underlying [[com.twitter.product_mixer.core.model.common.Component Component]]s and
- * [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]]s so [[AsyncFeatureMap]]s are scoped
- * for a specific [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]] only.
- */
-@JsonSerialize(using = classOf[AsyncFeatureMapSerializer])
-private[core] case class AsyncFeatureMap(
- asyncFeatureMaps: Map[PipelineStepIdentifier, Queue[
- (FeatureHydratorIdentifier, Set[Feature[_, _]], Stitch[FeatureMap])
- ]]) {
-
- def ++(right: AsyncFeatureMap): AsyncFeatureMap = {
- val map = Map.newBuilder[
- PipelineStepIdentifier,
- Queue[(FeatureHydratorIdentifier, Set[Feature[_, _]], Stitch[FeatureMap])]]
- (asyncFeatureMaps.keysIterator ++ right.asyncFeatureMaps.keysIterator).foreach { key =>
- val currentThenRightAsyncFeatureMaps =
- asyncFeatureMaps.getOrElse(key, Queue.empty) ++
- right.asyncFeatureMaps.getOrElse(key, Queue.empty)
- map += (key -> currentThenRightAsyncFeatureMaps)
- }
- AsyncFeatureMap(map.result())
- }
-
- /**
- * Returns a new [[AsyncFeatureMap]] which now keeps track of the provided `features`
- * and will make them available when calling [[hydrate]] with `hydrateBefore`.
- *
- * @param featureHydratorIdentifier the [[FeatureHydratorIdentifier]] of the [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator FeatureHydrator]]
- * which these [[Feature]]s are from
- * @param hydrateBefore the [[PipelineStepIdentifier]] before which the [[Feature]]s need to be hydrated
- * @param featuresToHydrate a Set of the [[Feature]]s which will be hydrated
- * @param features a [[Stitch]] of the [[FeatureMap]]
- */
- def addAsyncFeatures(
- featureHydratorIdentifier: FeatureHydratorIdentifier,
- hydrateBefore: PipelineStepIdentifier,
- featuresToHydrate: Set[Feature[_, _]],
- features: Stitch[FeatureMap]
- ): AsyncFeatureMap = {
- val featureMapList =
- asyncFeatureMaps.getOrElse(hydrateBefore, Queue.empty) :+
- ((featureHydratorIdentifier, featuresToHydrate, features))
- AsyncFeatureMap(asyncFeatureMaps + (hydrateBefore -> featureMapList))
- }
-
- /**
- * The current state of the [[AsyncFeatureMap]] excluding the [[Stitch]]s.
- */
- def features: Map[PipelineStepIdentifier, Seq[(FeatureHydratorIdentifier, Set[Feature[_, _]])]] =
- asyncFeatureMaps.mapValues(_.map {
- case (featureHydratorIdentifier, features, _) => (featureHydratorIdentifier, features)
- })
-
- /**
- * Returns a [[Some]] containing a [[Stitch]] with a [[FeatureMap]] holding the [[Feature]]s that are
- * supposed to be hydrated at `identifier` if there are [[Feature]]s to hydrate at `identifier`
- *
- * Returns [[None]] if there are no [[Feature]]s to hydrate at the provided `identifier`,
- * this allows for determining if there is work to do without running a [[Stitch]].
- *
- * @note this only hydrates the [[Feature]]s for the specific `identifier`, it does not hydrate
- * [[Feature]]s for earlier Steps.
- * @param identifier the [[PipelineStepIdentifier]] to hydrate [[Feature]]s for
- */
- def hydrate(
- identifier: PipelineStepIdentifier
- ): Option[Stitch[FeatureMap]] =
- asyncFeatureMaps.get(identifier) match {
- case Some(Queue((_, _, featureMap))) =>
- // if there is only 1 `FeatureMap` we dont need to do a collect so just return that Stitch
- Some(featureMap)
- case Some(featureMapList) =>
- // if there are multiple `FeatureMap`s we need to collect and merge them together
- Some(
- Stitch
- .collect(featureMapList.map { case (_, _, featureMap) => featureMap })
- .map { featureMapList => FeatureMap.merge(featureMapList) })
- case None =>
- // No results for the provided `identifier` so return `None`
- None
- }
-}
-
-private[core] object AsyncFeatureMap {
- val empty: AsyncFeatureMap = AsyncFeatureMap(Map.empty)
-
- /**
- * Builds the an [[AsyncFeatureMap]] from a Seq of [[Stitch]] of [[FeatureMap]]
- * tupled with the relevant metadata we use to build the necessary state.
- *
- * This is primarily for convenience, since in most cases an [[AsyncFeatureMap]]
- * will be built from the result of individual [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator FeatureHydrator]]s
- * and combining them into the correct internal state.
- */
- def fromFeatureMaps(
- asyncFeatureMaps: Seq[
- (FeatureHydratorIdentifier, PipelineStepIdentifier, Set[Feature[_, _]], Stitch[FeatureMap])
- ]
- ): AsyncFeatureMap =
- AsyncFeatureMap(
- asyncFeatureMaps
- .groupBy { case (_, hydrateBefore, _, _) => hydrateBefore }
- .mapValues(featureMaps =>
- Queue(featureMaps.map {
- case (hydratorIdentifier, _, featuresToHydrate, stitch) =>
- (hydratorIdentifier, featuresToHydrate, stitch)
- }: _*)))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala
deleted file mode 100644
index 2ed4c6735..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-
-/**
- * Since an [[AsyncFeatureMap]] is typically incomplete, and by the time it's serialized, all the [[com.twitter.product_mixer.core.feature.Feature]]s
- * it will typically be completed and part of the Query or Candidate's individual [[com.twitter.product_mixer.core.feature.Feature]]s
- * we instead opt to provide a summary of the Features which would be hydrated using [[AsyncFeatureMap.features]]
- *
- * This indicates which [[com.twitter.product_mixer.core.feature.Feature]]s will be ready at which Steps
- * and which [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]]
- * are responsible for those [[com.twitter.product_mixer.core.feature.Feature]]
- *
- * @note changes to serialization logic can have serious performance implications given how hot the
- * serialization path is. Consider benchmarking changes with [[com.twitter.product_mixer.core.benchmark.AsyncQueryFeatureMapSerializationBenchmark]]
- */
-private[asyncfeaturemap] class AsyncFeatureMapSerializer() extends JsonSerializer[AsyncFeatureMap] {
- override def serialize(
- asyncFeatureMap: AsyncFeatureMap,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit = {
- gen.writeStartObject()
-
- asyncFeatureMap.features.foreach {
- case (stepIdentifier, featureHydrators) =>
- gen.writeObjectFieldStart(stepIdentifier.toString)
-
- featureHydrators.foreach {
- case (hydratorIdentifier, featuresFromHydrator) =>
- gen.writeArrayFieldStart(hydratorIdentifier.toString)
-
- featuresFromHydrator.foreach(feature => gen.writeString(feature.toString))
-
- gen.writeEndArray()
- }
-
- gen.writeEndObject()
- }
-
- gen.writeEndObject()
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD
deleted file mode 100644
index 2d193a3b8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "stitch/stitch-core",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD
deleted file mode 100644
index 8511d47bc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/java/com/twitter/ml/api:api-base",
- "src/scala/com/twitter/ml/api/util:datarecord",
- "util/util-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala
deleted file mode 100644
index 56533bd88..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.datarecord
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.ml.api.DataRecordMerger
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.datarecord._
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-
-object DataRecordConverter {
- val merger = new DataRecordMerger
-}
-
-/**
- * Constructs a FeatureMap from a DataRecord, given a predefined set of features from a FeaturesScope.
- *
- * @param featuresScope scope of predefined set of BaseDataRecordFeatures that should be included in the output FeatureMap.
- */
-class DataRecordConverter[DRFeature <: BaseDataRecordFeature[_, _]](
- featuresScope: FeaturesScope[DRFeature]) {
- import DataRecordConverter._
-
- def toDataRecord(featureMap: FeatureMap): DataRecord = {
- // Initialize a DataRecord with the Feature Store features in it and then add all the
- // non-Feature Store features that support DataRecords to DataRecord. We don't
- // need to add Feature Store features because they're already in the initial DataRecord.
- // If there are any pre-built DataRecords, we merge those in.
- val richDataRecord = featuresScope.getFeatureStoreFeaturesDataRecord(featureMap)
- val features = featuresScope.getNonFeatureStoreDataRecordFeatures(featureMap)
- features.foreach {
- case _: FeatureStoreDataRecordFeature[_, _] =>
- case requiredFeature: DataRecordFeature[_, _] with DataRecordCompatible[_] =>
- richDataRecord.setFeatureValue(
- requiredFeature.mlFeature,
- requiredFeature.toDataRecordFeatureValue(
- featureMap.get(requiredFeature).asInstanceOf[requiredFeature.FeatureType]))
- case optionalFeature: DataRecordOptionalFeature[_, _] with DataRecordCompatible[_] =>
- featureMap
- .get(
- optionalFeature.asInstanceOf[Feature[_, Option[optionalFeature.FeatureType]]]).foreach {
- value =>
- richDataRecord
- .setFeatureValue(
- optionalFeature.mlFeature,
- optionalFeature.toDataRecordFeatureValue(value))
- }
- case dataRecordInAFeature: DataRecordInAFeature[_] =>
- merger.merge(richDataRecord.getRecord, featureMap.get(dataRecordInAFeature))
- }
- richDataRecord.getRecord
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala
deleted file mode 100644
index a91b01d22..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.datarecord
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.ml.api.FeatureContext
-import com.twitter.ml.api.util.SRichDataRecord
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.datarecord._
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import scala.collection.JavaConverters._
-
-/**
- * Constructs a DataRecord from a FeatureMap, given a predefined set of features.
- *
- * @param features predefined set of BaseDataRecordFeatures that should be included in the output DataRecord.
- */
-class DataRecordExtractor[DRFeature <: BaseDataRecordFeature[_, _]](
- features: Set[DRFeature]) {
-
- private val featureContext = new FeatureContext(features.collect {
- case dataRecordCompatible: DataRecordCompatible[_] => dataRecordCompatible.mlFeature
- }.asJava)
-
- def fromDataRecord(dataRecord: DataRecord): FeatureMap = {
- val featureMapBuilder = FeatureMapBuilder()
- val richDataRecord = SRichDataRecord(dataRecord, featureContext)
- features.foreach {
- // FeatureStoreDataRecordFeature is currently not supported
- case _: FeatureStoreDataRecordFeature[_, _] =>
- throw new UnsupportedOperationException(
- "FeatureStoreDataRecordFeature cannot be extracted from a DataRecord")
- case feature: DataRecordFeature[_, _] with DataRecordCompatible[_] =>
- // Java API will return null, so use Option to convert it to Scala Option which is None when null.
- richDataRecord.getFeatureValueOpt(feature.mlFeature)(
- feature.fromDataRecordFeatureValue) match {
- case Some(value) =>
- featureMapBuilder.add(feature.asInstanceOf[Feature[_, feature.FeatureType]], value)
- case None =>
- featureMapBuilder.addFailure(
- feature,
- PipelineFailure(
- IllegalStateFailure,
- s"Required DataRecord feature is missing: ${feature.mlFeature.getFeatureName}")
- )
- }
- case feature: DataRecordOptionalFeature[_, _] with DataRecordCompatible[_] =>
- val featureValue =
- richDataRecord.getFeatureValueOpt(feature.mlFeature)(feature.fromDataRecordFeatureValue)
- featureMapBuilder
- .add(feature.asInstanceOf[Feature[_, Option[feature.FeatureType]]], featureValue)
- // DataRecordInAFeature is currently not supported
- case _: DataRecordInAFeature[_] =>
- throw new UnsupportedOperationException(
- "DataRecordInAFeature cannot be extracted from a DataRecord")
- }
- featureMapBuilder.build()
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala
deleted file mode 100644
index 8ef1898a9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.datarecord
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.ml.api.FeatureContext
-import com.twitter.ml.api.util.SRichDataRecord
-import scala.collection.JavaConverters._
-import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature
-import com.twitter.product_mixer.core.feature.datarecord.DataRecordCompatible
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1Feature
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-
-/**
- * FeaturesScope for defining what features should be included in a DataRecord from a FeatureMap.
- * Where possible, prefer [[SpecificFeatures]]. It fails loudly on missing features which can help
- * identify programmer error, but can be complex to manage for multi-phase hydrators.
- */
-sealed trait FeaturesScope[+DRFeature <: BaseDataRecordFeature[_, _]] {
- def getNonFeatureStoreDataRecordFeatures(featureMap: FeatureMap): Seq[DRFeature]
-
- /**
- * Because Feature Store features aren't direct features in the FeatureMap and instead live
- * aggregated in a DataRecord in our Feature Map, we need to interface with the underlying Data
- * Record instead. e.g. for the `AllFeatures` case, we won't know what all FStore ProMix Features
- * we have in a FeatureMap just by looping through features & need to just return the DataRecord.
- */
- def getFeatureStoreFeaturesDataRecord(featureMap: FeatureMap): SRichDataRecord
-}
-
-/**
- * Use all DataRecord features on a FeatureMap to output a DataRecord.
- */
-case class AllFeatures[-Entity]() extends FeaturesScope[BaseDataRecordFeature[Entity, _]] {
- override def getNonFeatureStoreDataRecordFeatures(
- featureMap: FeatureMap
- ): Seq[BaseDataRecordFeature[Entity, _]] = {
-
- /**
- * See [[com.twitter.product_mixer.core.benchmark.FeatureMapBenchmark]]
- *
- * `toSeq`` is a no-op, `view`` makes later compositions lazy. Currently we only perform a `forEach`
- * on the result but `view` here has no performance impact but protects us if we accidentally add
- * more compositions in the middle.
- *
- * Feature Store features aren't in the FeatureMap so this will only ever return the non-FStore Features.
- */
- featureMap.getFeatures.toSeq.view.collect {
- case feature: BaseDataRecordFeature[Entity, _] => feature
- }
- }
-
- // Get the entire underlying DataRecord if available.
- override def getFeatureStoreFeaturesDataRecord(
- featureMap: FeatureMap
- ): SRichDataRecord = if (featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) {
- // Note, we do not copy over the feature context because JRichDataRecord will enforce that
- // all features are in the FeatureContext which we do not know at init time, and it's pricey
- // to compute at run time.
- SRichDataRecord(featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord.getRecord)
- } else {
- SRichDataRecord(new DataRecord())
- }
-}
-
-/**
- * Build a DataRecord with only the given features from the FeatureMap used. Missing features
- * will fail loudly.
- * @param features the specific features to include in the DataRecord.
- */
-case class SpecificFeatures[DRFeature <: BaseDataRecordFeature[_, _]](
- features: Set[DRFeature])
- extends FeaturesScope[DRFeature] {
-
- private val featuresForContext = features.collect {
- case featureStoreFeatures: FeatureStoreV1Feature[_, _, _, _] =>
- featureStoreFeatures.boundFeature.mlApiFeature
- case dataRecordCompatible: DataRecordCompatible[_] => dataRecordCompatible.mlFeature
- }.asJava
-
- private val featureContext = new FeatureContext(featuresForContext)
-
- private val fsFeatures = features
- .collect {
- case featureStoreV1Feature: FeatureStoreV1Feature[_, _, _, _] =>
- featureStoreV1Feature
- }
-
- // Since it's possible a customer will pass feature store features in the DR Feature list, let's
- // partition them out to only return non-FS ones in getFeatures. See [[FeaturesScope]] comment.
- private val nonFsFeatures: Seq[DRFeature] = features.flatMap {
- case _: FeatureStoreV1Feature[_, _, _, _] =>
- None
- case otherFeature => Some(otherFeature)
- }.toSeq
-
- override def getNonFeatureStoreDataRecordFeatures(
- featureMap: FeatureMap
- ): Seq[DRFeature] = nonFsFeatures
-
- override def getFeatureStoreFeaturesDataRecord(
- featureMap: FeatureMap
- ): SRichDataRecord =
- if (fsFeatures.nonEmpty && featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) {
- // Return a DataRecord only with the explicitly requested features set.
- val richDataRecord = SRichDataRecord(new DataRecord(), featureContext)
- val existingDataRecord = featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord
- fsFeatures.foreach { feature =>
- richDataRecord.setFeatureValue(
- feature.boundFeature.mlApiFeature,
- existingDataRecord.getFeatureValue(feature.boundFeature.mlApiFeature))
- }
- richDataRecord
- } else {
- SRichDataRecord(new DataRecord())
- }
-}
-
-/**
- * Build a DataRecord with every feature available in a FeatureMap except for the ones provided.
- * @param featuresToExclude the features to be excluded in the DataRecord.
- */
-case class AllExceptFeatures(
- featuresToExclude: Set[BaseDataRecordFeature[_, _]])
- extends FeaturesScope[BaseDataRecordFeature[_, _]] {
-
- private val fsFeatures = featuresToExclude
- .collect {
- case featureStoreV1Feature: FeatureStoreV1Feature[_, _, _, _] =>
- featureStoreV1Feature
- }
-
- override def getNonFeatureStoreDataRecordFeatures(
- featureMap: FeatureMap
- ): Seq[BaseDataRecordFeature[_, _]] =
- featureMap.getFeatures
- .collect {
- case feature: BaseDataRecordFeature[_, _] => feature
- }.filterNot(featuresToExclude.contains).toSeq
-
- override def getFeatureStoreFeaturesDataRecord(
- featureMap: FeatureMap
- ): SRichDataRecord = if (featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) {
- // Return a data record only with the explicitly requested features set. Do this by copying
- // the existing one and removing the features in the denylist.
- // Note, we do not copy over the feature context because JRichDataRecord will enforce that
- // all features are in the FeatureContext which we do not know at init time, and it's pricey
- // to compute at run time.
- val richDataRecord = SRichDataRecord(
- featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord.getRecord.deepCopy())
- fsFeatures.foreach { feature =>
- richDataRecord.clearFeature(feature.boundFeature.mlApiFeature)
- }
- richDataRecord
- } else {
- SRichDataRecord(new DataRecord())
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD
deleted file mode 100644
index b34c59913..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala
deleted file mode 100644
index 54abfc05e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala
+++ /dev/null
@@ -1,191 +0,0 @@
-package com.twitter.product_mixer.core.feature.featuremap.featurestorev1
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeatureGroup
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeatureGroup
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.util.Try
-
-object FeatureStoreV1FeatureMap {
-
- /**
- * Implicitly add convenience accessors for FeatureStoreV1 features in [[FeatureMap]]. Note that
- * we cannot add these methods directly to [[FeatureMap]] because it would introduce a circular
- * dependency ([[PipelineQuery]] depends on [[FeatureMap]], and the methods below depend on
- * [[PipelineQuery]])
- *
- * @param featureMap the featureMap we are wrapping
- * @note The FeatureStoreV1Feature::defaultValue set on the BoundFeature is only used and set
- * during PredictionRecord to DataRecord conversion. Therefore, the default will not be set
- * on the PredictionRecord value if reading from it directly, and as such for convenience
- * the defaultValue is manually returned during retrieval from PredictionRecord.
- * @note the Value generic type on the methods below cannot be passed to
- * FeatureStoreV1QueryFeature's Value generic type. While this is actually the same type,
- * (note the explicit type cast back to Value), we must instead use an existential on
- * FeatureStoreV1QueryFeature since it is constructed with an existential for the Value
- * generic (see [[FeatureStoreV1QueryFeature]] and [[FeatureStoreV1CandidateFeature]])
- */
- implicit class FeatureStoreV1FeatureMapAccessors(private val featureMap: FeatureMap) {
-
- def getFeatureStoreV1QueryFeature[Query <: PipelineQuery, Value](
- feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value]
- ): Value =
- getOrElseFeatureStoreV1QueryFeature(
- feature,
- feature.defaultValue.getOrElse {
- throw MissingFeatureException(feature)
- })
-
- def getFeatureStoreV1QueryFeatureTry[Query <: PipelineQuery, Value](
- feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value]
- ): Try[Value] =
- Try(getFeatureStoreV1QueryFeature(feature))
-
- def getOrElseFeatureStoreV1QueryFeature[Query <: PipelineQuery, Value](
- feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value],
- default: => Value
- ): Value = {
-
- /**
- * FeatureStoreV1ResponseFeature should never be missing from the FeatureMap as FSv1 is
- * guaranteed to return a prediction record per feature store request. However, this may be
- * called on candidates that never hydrated FSv1 features. For example by
- * [[com.twitter.product_mixer.component_library.selector.sorter.featurestorev1.FeatureStoreV1FeatureValueSorter]]
- */
- val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption
-
- val dataRecordValue: Option[Value] = featureStoreV1FeatureValueOpt.flatMap {
- featureStoreV1FeatureValue =>
- featureStoreV1FeatureValue.richDataRecord.getFeatureValueOpt(
- feature.boundFeature.mlApiFeature)(feature.fromDataRecordValue)
- }
-
- dataRecordValue.getOrElse(default)
- }
-
- def getFeatureStoreV1CandidateFeature[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- Value
- ](
- feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value]
- ): Value =
- getOrElseFeatureStoreV1CandidateFeature(
- feature,
- feature.defaultValue.getOrElse {
- throw MissingFeatureException(feature)
- })
-
- def getFeatureStoreV1CandidateFeatureTry[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- Value
- ](
- feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value]
- ): Try[Value] =
- Try(getFeatureStoreV1CandidateFeature(feature))
-
- def getOrElseFeatureStoreV1CandidateFeature[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- Value
- ](
- feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value],
- default: => Value
- ): Value = {
-
- /**
- * FeatureStoreV1ResponseFeature should never be missing from the FeatureMap as FSv1 is
- * guaranteed to return a prediction record per feature store request. However, this may be
- * called on candidates that never hydrated FSv1 features. For example by
- * [[com.twitter.product_mixer.component_library.selector.sorter.featurestorev1.FeatureStoreV1FeatureValueSorter]]
- */
- val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption
-
- val dataRecordValue: Option[Value] = featureStoreV1FeatureValueOpt.flatMap {
- featureStoreV1FeatureValue =>
- featureStoreV1FeatureValue.richDataRecord.getFeatureValueOpt(
- feature.boundFeature.mlApiFeature)(feature.fromDataRecordValue)
- }
-
- dataRecordValue.getOrElse(default)
- }
-
- /**
- * Get queryFeatureGroup, which is store in the featureMap as a DataRecordInAFeature
- * It doesn't have the mlApiFeature as other regular FeatureStoreV1 features
- * Please refer to [[com.twitter.product_mixer.core.feature.datarecord.DataRecordInAFeature]] scaladoc for more details
- */
- def getFeatureStoreV1QueryFeatureGroup[Query <: PipelineQuery](
- featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId]
- ): DataRecord =
- getOrElseFeatureStoreV1QueryFeatureGroup(
- featureGroup,
- throw MissingFeatureException(featureGroup)
- )
-
- def getFeatureStoreV1CandidateFeatureGroupTry[Query <: PipelineQuery](
- featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId]
- ): Try[DataRecord] =
- Try(getFeatureStoreV1QueryFeatureGroup(featureGroup))
-
- def getOrElseFeatureStoreV1QueryFeatureGroup[Query <: PipelineQuery](
- featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId],
- default: => DataRecord
- ): DataRecord = {
- featureMap.getTry(featureGroup).toOption.getOrElse(default)
- }
-
- /**
- * Get candidateFeatureGroup, which is store in the featureMap as a DataRecordInAFeature
- * It doesn't have the mlApiFeature as other regular FeatureStoreV1 features
- * Please refer to [[com.twitter.product_mixer.core.feature.datarecord.DataRecordInAFeature]] scaladoc for more details
- */
- def getFeatureStoreV1CandidateFeatureGroup[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ](
- featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId]
- ): DataRecord =
- getOrElseFeatureStoreV1CandidateFeatureGroup(
- featureGroup,
- throw MissingFeatureException(featureGroup)
- )
-
- def getFeatureStoreV1CandidateFeatureGroupTry[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ](
- featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId]
- ): Try[DataRecord] =
- Try(getFeatureStoreV1CandidateFeatureGroup(featureGroup))
-
- def getOrElseFeatureStoreV1CandidateFeatureGroup[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ](
- featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId],
- default: => DataRecord
- ): DataRecord = {
- featureMap.getTry(featureGroup).toOption.getOrElse(default)
- }
-
- def getOrElseFeatureStoreV1FeatureDataRecord(
- default: => DataRecord
- ) = {
- val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption
-
- featureStoreV1FeatureValueOpt
- .map { featureStoreV1FeatureValue =>
- featureStoreV1FeatureValue.richDataRecord.getRecord
- }.getOrElse(default)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD
deleted file mode 100644
index 408a2b569..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD
+++ /dev/null
@@ -1,29 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/scala/com/twitter/ml/featurestore/catalog/entities/core",
- "src/scala/com/twitter/ml/featurestore/lib/data",
- "src/scala/com/twitter/ml/featurestore/lib/dynamic",
- "src/scala/com/twitter/ml/featurestore/lib/feature",
- "src/scala/com/twitter/ml/featurestore/lib/feature:aggregates-feature-group",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "src/scala/com/twitter/ml/featurestore/catalog/entities/core",
- "src/scala/com/twitter/ml/featurestore/lib/data",
- "src/scala/com/twitter/ml/featurestore/lib/dynamic",
- "src/scala/com/twitter/ml/featurestore/lib/feature",
- "src/scala/com/twitter/ml/featurestore/lib/feature:aggregates-feature-group",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala
deleted file mode 100644
index bd47a18c4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.feature.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.entity.Entity
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-sealed trait FeatureStoreV1Entity[
- -Query <: PipelineQuery,
- -Input,
- FeatureStoreEntityId <: EntityId] {
-
- val entity: Entity[FeatureStoreEntityId]
-}
-
-trait FeatureStoreV1QueryEntity[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId]
- extends FeatureStoreV1Entity[Query, Query, FeatureStoreEntityId] {
-
- def entityWithId(query: Query): EntityWithId[FeatureStoreEntityId]
-}
-
-trait FeatureStoreV1CandidateEntity[
- -Query <: PipelineQuery,
- -Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId]
- extends FeatureStoreV1Entity[Query, Input, FeatureStoreEntityId] {
-
- def entityWithId(
- query: Query,
- input: Input,
- existingFeatures: FeatureMap
- ): EntityWithId[FeatureStoreEntityId]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala
deleted file mode 100644
index 0dc64e19e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala
+++ /dev/null
@@ -1,312 +0,0 @@
-package com.twitter.product_mixer.core.feature.featurestorev1
-
-import com.twitter.ml.api.DataRecord
-import com.twitter.ml.api.transform.FeatureRenameTransform
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.dynamic.BaseGatedFeatures
-import com.twitter.ml.featurestore.lib.feature.BoundFeature
-import com.twitter.ml.featurestore.lib.feature.BoundFeatureSet
-import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup
-import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature}
-import com.twitter.product_mixer.core.feature.ModelFeatureName
-import com.twitter.product_mixer.core.feature.datarecord.FeatureStoreDataRecordFeature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.servo.util.{Gate => ServoGate}
-import com.twitter.timelines.configapi.FSParam
-import scala.reflect.ClassTag
-
-/**
- * The base trait for all feature store features on ProMix. This should not be constructed directly
- * and should instead be used through the other implementations below
- * @tparam Query Product Mixer Query Type
- * @tparam Input The input type the feature should be keyed on, this is same as Query for query
- * features and
- * @tparam FeatureStoreEntityId Feature Store Entity Type
- * @tparam Value The type of the value of this feature.
- */
-sealed trait BaseFeatureStoreV1Feature[
- -Query <: PipelineQuery,
- -Input,
- FeatureStoreEntityId <: EntityId,
- Value]
- extends FeatureStoreDataRecordFeature[Input, Value]
- with BaseGatedFeatures[Query] {
- val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value]
-
- val entity: FeatureStoreV1Entity[Query, Input, FeatureStoreEntityId]
-
- val enabledParam: Option[FSParam[Boolean]]
-
- override final lazy val gate: ServoGate[Query] = enabledParam
- .map { param =>
- new ServoGate[PipelineQuery] {
- override def apply[U](query: U)(implicit asT: <:<[U, PipelineQuery]): Boolean = {
- query.params(param)
- }
- }
- }.getOrElse(ServoGate.True)
-
- override final lazy val boundFeatureSet: BoundFeatureSet = new BoundFeatureSet(Set(boundFeature))
-
- val boundFeature: BoundFeature[FeatureStoreEntityId, Value]
-
- /**
- * Since this trait is normally constructed inline, avoid the anonymous toString and use the bounded feature name.
- */
- override lazy val toString: String = boundFeature.name
-}
-
-/**
- * A unitary (non-aggregate group) feature store feature in ProMix. This should be constructed using
- * [[FeatureStoreV1CandidateFeature]] or [[FeatureStoreV1QueryFeature]].
- * @tparam Query Product Mixer Query Type
- * @tparam Input The input type the feature should be keyed on, this is same as Query for query
- * features and
- * @tparam FeatureStoreEntityId Feature Store Entity Type
- * @tparam Value The type of the value of this feature.
- */
-sealed trait FeatureStoreV1Feature[
- -Query <: PipelineQuery,
- -Input,
- FeatureStoreEntityId <: EntityId,
- Value]
- extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value]
- with ModelFeatureName {
-
- val legacyName: Option[String]
- val defaultValue: Option[Value]
-
- override lazy val featureName: String = boundFeature.name
-
- override final lazy val boundFeature = (legacyName, defaultValue) match {
- case (Some(legacyName), Some(defaultValue)) =>
- fsv1Feature.bind(entity.entity).withLegacyName(legacyName).withDefault(defaultValue)
- case (Some(legacyName), _) =>
- fsv1Feature.bind(entity.entity).withLegacyName(legacyName)
- case (_, Some(defaultValue)) =>
- fsv1Feature.bind(entity.entity).withDefault(defaultValue)
- case _ =>
- fsv1Feature.bind(entity.entity)
- }
-
- def fromDataRecordValue(recordValue: boundFeature.feature.mfc.V): Value =
- boundFeature.feature.mfc.fromDataRecordValue(recordValue)
-}
-
-/**
- * A feature store aggregated group feature in ProMix. This should be constructed using
- * [[FeatureStoreV1CandidateFeatureGroup]] or [[FeatureStoreV1QueryFeatureGroup]].
- *
- * @tparam Query Product Mixer Query Type
- * @tparam Input The input type the feature should be keyed on, this is same as Query for query
- * features and
- * @tparam FeatureStoreEntityId Feature Store Entity Type
- */
-abstract class FeatureStoreV1FeatureGroup[
- -Query <: PipelineQuery,
- -Input,
- FeatureStoreEntityId <: EntityId: ClassTag]
- extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, DataRecord] {
- val keepLegacyNames: Boolean
- val featureNameTransform: Option[FeatureRenameTransform]
-
- val featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId]
-
- override lazy val fsv1Feature: FSv1Feature[FeatureStoreEntityId, DataRecord] =
- featureGroup.FeaturesAsDataRecord
-
- override final lazy val boundFeature = (keepLegacyNames, featureNameTransform) match {
- case (_, Some(transform)) =>
- fsv1Feature.bind(entity.entity).withLegacyIndividualFeatureNames(transform)
- case (true, _) =>
- fsv1Feature.bind(entity.entity).keepLegacyNames
- case _ =>
- fsv1Feature.bind(entity.entity)
- }
-}
-
-sealed trait BaseFeatureStoreV1QueryFeature[
- -Query <: PipelineQuery,
- FeatureStoreEntityId <: EntityId,
- Value]
- extends BaseFeatureStoreV1Feature[Query, Query, FeatureStoreEntityId, Value] {
-
- override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId]
-}
-
-trait FeatureStoreV1QueryFeature[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId, Value]
- extends FeatureStoreV1Feature[Query, Query, FeatureStoreEntityId, Value]
- with BaseFeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value]
-
-trait FeatureStoreV1QueryFeatureGroup[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId]
- extends FeatureStoreV1FeatureGroup[Query, Query, FeatureStoreEntityId]
- with BaseFeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, DataRecord]
-
-object FeatureStoreV1QueryFeature {
-
- /**
- * Query-based Feature Store backed feature
- * @param feature The underling feature store feature this represents.
- * @param _entity The entity for binding the Feature Store features
- * @param _legacyName Feature Store legacy name if required
- * @param _defaultValue The default value to return for this feature if not hydrated.
- * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none.
- * @tparam Query The Product Mixer query type this feature is keyed on.
- * @tparam FeatureStoreEntityId Feature Store Entity ID
- * @tparam Value The type of the value this feature contains.
- * @return Product Mixer Feature
- */
- def apply[Query <: PipelineQuery, FeatureStoreEntityId <: EntityId, Value](
- feature: FSv1Feature[FeatureStoreEntityId, Value],
- _entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId],
- _legacyName: Option[String] = None,
- _defaultValue: Option[Value] = None,
- _enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value] =
- new FeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value] {
- override val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value] = feature
- override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId] = _entity
- override val legacyName: Option[String] = _legacyName
- override val defaultValue: Option[Value] = _defaultValue
- override val enabledParam: Option[FSParam[Boolean]] = _enabledParam
- }
-}
-
-object FeatureStoreV1QueryFeatureGroup {
-
- /**
- * Query-based Feature Store Aggregated group backed feature
- *
- * @param featureGroup The underling aggregation group feature this represents.
- * @param _entity The entity for binding the Feature Store features
- * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none.
- * @param _keepLegacyNames Whether to keep the legacy names as is for the entire group
- * @param _featureNameTransform Rename the entire group's legacy names using the [[FeatureRenameTransform]]
- * @tparam Query The Product Mixer query type this feature is keyed on.
- * @tparam FeatureStoreEntityId Feature Store Entity ID
- *
- * @return Product Mixer Feature
- */
- def apply[Query <: PipelineQuery, FeatureStoreEntityId <: EntityId: ClassTag](
- _featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId],
- _entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId],
- _enabledParam: Option[FSParam[Boolean]] = None,
- _keepLegacyNames: Boolean = false,
- _featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1QueryFeatureGroup[Query, FeatureStoreEntityId] =
- new FeatureStoreV1QueryFeatureGroup[Query, FeatureStoreEntityId] {
- override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId] = _entity
- override val featureGroup: TimelinesAggregationFrameworkFeatureGroup[
- FeatureStoreEntityId
- ] = _featureGroup
-
- override val enabledParam: Option[FSParam[Boolean]] = _enabledParam
-
- override val keepLegacyNames: Boolean = _keepLegacyNames
- override val featureNameTransform: Option[FeatureRenameTransform] = _featureNameTransform
- }
-}
-
-sealed trait BaseFeatureStoreV1CandidateFeature[
- -Query <: PipelineQuery,
- -Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId,
- Value]
- extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value] {
-
- override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId]
-}
-
-trait FeatureStoreV1CandidateFeature[
- -Query <: PipelineQuery,
- -Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId,
- Value]
- extends FeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value]
- with BaseFeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value]
-
-trait FeatureStoreV1CandidateFeatureGroup[
- -Query <: PipelineQuery,
- -Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId]
- extends FeatureStoreV1FeatureGroup[Query, Input, FeatureStoreEntityId]
- with BaseFeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, DataRecord]
-
-object FeatureStoreV1CandidateFeature {
-
- /**
- * Candidate-based Feature Store backed feature
- * @param feature The underling feature store feature this represents.
- * @param _entity The entity for binding the Feature Store features
- * @param _legacyName Feature Store legacy name if required
- * @param _defaultValue The default value to return for this feature if not hydrated.
- * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none.
- * @tparam Query The Product Mixer query type this feature is keyed on.
- * @tparam FeatureStoreEntityId The feature store entity type
- * @tparam Input The type of the candidate this feature is keyed on
- * @tparam Value The type of value this feature contains.
- * @return Product Mixer Feature
- */
- def apply[
- Query <: PipelineQuery,
- Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId,
- Value
- ](
- feature: FSv1Feature[FeatureStoreEntityId, Value],
- _entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId],
- _legacyName: Option[String] = None,
- _defaultValue: Option[Value] = None,
- _enabledParam: Option[FSParam[Boolean]] = None
- ): FeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value] =
- new FeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value] {
- override val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value] = feature
- override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId] =
- _entity
- override val legacyName: Option[String] = _legacyName
- override val defaultValue: Option[Value] = _defaultValue
- override val enabledParam: Option[FSParam[Boolean]] = _enabledParam
- }
-}
-
-object FeatureStoreV1CandidateFeatureGroup {
-
- /**
- * Candidate-based Feature Store Aggregated group backed feature
- *
- * @param featureGroup The underling aggregation group feature this represents.
- * @param _entity The entity for binding the Feature Store features
- * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none.
- * @param _keepLegacyNames Whether to keep the legacy names as is for the entire group
- * @param _featureNameTransform Rename the entire group's legacy names using the [[FeatureRenameTransform]]
- * @tparam Query The Product Mixer query type this feature is keyed on.
- * @tparam Input The type of the candidate this feature is keyed on
- * @tparam FeatureStoreEntityId Feature Store Entity ID
- *
- * @return Product Mixer Feature
- */
- def apply[
- Query <: PipelineQuery,
- Input <: UniversalNoun[Any],
- FeatureStoreEntityId <: EntityId: ClassTag,
- ](
- _featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId],
- _entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId],
- _enabledParam: Option[FSParam[Boolean]] = None,
- _keepLegacyNames: Boolean = false,
- _featureNameTransform: Option[FeatureRenameTransform] = None
- ): FeatureStoreV1CandidateFeatureGroup[Query, Input, FeatureStoreEntityId] =
- new FeatureStoreV1CandidateFeatureGroup[Query, Input, FeatureStoreEntityId] {
- override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId] =
- _entity
- override val featureGroup: TimelinesAggregationFrameworkFeatureGroup[
- FeatureStoreEntityId
- ] = _featureGroup
-
- override val enabledParam: Option[FSParam[Boolean]] = _enabledParam
-
- override val keepLegacyNames: Boolean = _keepLegacyNames
- override val featureNameTransform: Option[FeatureRenameTransform] = _featureNameTransform
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD
deleted file mode 100644
index 931ea442a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "src/scala/com/twitter/ml/api/util:datarecord",
- "src/scala/com/twitter/ml/featurestore/lib/data",
- "src/scala/com/twitter/ml/featurestore/lib/dynamic",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "src/scala/com/twitter/ml/api/util:datarecord",
- "src/scala/com/twitter/ml/featurestore/lib/data",
- "src/scala/com/twitter/ml/featurestore/lib/dynamic",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala
deleted file mode 100644
index e1f495346..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.core.feature.featurestorev1.featurevalue
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.twitter.ml.api.DataRecordMerger
-import com.twitter.ml.api.util.SRichDataRecord
-import com.twitter.ml.featurestore.lib.data.HydrationError
-import com.twitter.product_mixer.core.feature.Feature
-
-private[product_mixer] object FeatureStoreV1ResponseFeature
- extends Feature[Any, FeatureStoreV1Response]
-
-@JsonIgnoreProperties(Array("richDataRecord", "failedFeatures"))
-private[product_mixer] case class FeatureStoreV1Response(
- @JsonProperty("richDataRecord") richDataRecord: SRichDataRecord,
- @JsonProperty("failedFeatures") failedFeatures: Map[_ <: Feature[_, _], Set[HydrationError]]) {
- // Since RichDataRecord is Java, we need to override this.
- override def equals(obj: Any): Boolean = obj match {
- case that: FeatureStoreV1Response =>
- failedFeatures == that.failedFeatures && richDataRecord.getRecord.equals(
- that.richDataRecord.getRecord)
- case _ => false
- }
-}
-
-private[product_mixer] object FeatureStoreV1Response {
- val dataRecordMerger = new DataRecordMerger
- def merge(
- left: FeatureStoreV1Response,
- right: FeatureStoreV1Response
- ): FeatureStoreV1Response = {
- val newDataRecord = left.richDataRecord.getRecord.deepCopy()
- dataRecordMerger.merge(newDataRecord, right.richDataRecord.getRecord)
- FeatureStoreV1Response(
- richDataRecord = SRichDataRecord(newDataRecord),
- left.failedFeatures ++ right.failedFeatures
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD
deleted file mode 100644
index cb0e59b7c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD
deleted file mode 100644
index fe3e5b6bb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala
deleted file mode 100644
index 2d93ab91a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-
-sealed trait BaseCandidateSource[-Request, +Candidate] extends Component {
-
- /** @see [[CandidateSourceIdentifier]] */
- val identifier: CandidateSourceIdentifier
-}
-
-/**
- * A [[CandidateSource]] returns a Seq of ''potential'' content
- *
- * @note [[CandidateSource]]s that return a single value need to transform
- * it into a Seq, either by doing `Seq(value)` or extracting
- * candidates from the value.
- *
- * @tparam Request arguments to get the potential content
- * @tparam Candidate the potential content
- */
-trait CandidateSource[-Request, +Candidate] extends BaseCandidateSource[Request, Candidate] {
-
- /** returns a Seq of ''potential'' content */
- def apply(request: Request): Stitch[Seq[Candidate]]
-}
-
-/**
- * A [[CandidateSourceWithExtractedFeatures]] returns a result containing both a Seq of
- * ''potential'' candidates as well as an extracted feature map that will later be appended
- * to the pipeline's [[com.twitter.product_mixer.core.pipeline.PipelineQuery]] feature map. This is
- * useful for candidate sources that return features that might be useful later on without needing
- * to re-hydrate them.
- *
- * @note [[CandidateSource]]s that return a single value need to transform
- * it into a Seq, either by doing `Seq(value)` or extracting
- * candidates from the value.
- *
- * @tparam Request arguments to get the potential content
- * @tparam Candidate the potential content
- */
-trait CandidateSourceWithExtractedFeatures[-Request, +Candidate]
- extends BaseCandidateSource[Request, Candidate] {
-
- /** returns a result containing a seq of ''potential'' content and extracted features
- * from the candidate source.
- * */
- def apply(request: Request): Stitch[CandidatesWithSourceFeatures[Candidate]]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala
deleted file mode 100644
index 124f9a044..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-
-/**
- * Results from a candidate source, optionally carrying extracted query level features to add
- * to the query's feature map (e.g, extracting reusable features from the thrift response of thrift
- * call).
- * @param candidates The candidates returned from the underlying CandidateSoure
- * @param features [[FeatureMap]] containing the features from the candidate source
- * to merge back into the PipelineQuery FeatureMap.
- * @tparam Candidate The type of result
- */
-case class CandidatesWithSourceFeatures[+Candidate](
- candidates: Seq[Candidate],
- features: FeatureMap)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala
deleted file mode 100644
index ff51cace1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Retrieve Candidates from the Query
- */
-trait CandidateExtractor[-Request, +Candidate] {
-
- def apply(query: Request): Seq[Candidate]
-}
-
-/**
- * Identity extractor for returning the Request as a Seq of candidates
- */
-case class IdentityCandidateExtractor[Request]() extends CandidateExtractor[Request, Request] {
-
- def apply(candidate: Request): Seq[Request] = Seq(candidate)
-}
-
-/**
- * Retrieve Candidates from a [[Feature]] on the [[PipelineQuery]]'s FeatureMap. This extractor
- * supports a transform if the Feature value and the Seq of [[Candidate]] types do not match
- */
-trait QueryFeatureCandidateExtractor[-Query <: PipelineQuery, FeatureValue, +Candidate]
- extends CandidateExtractor[Query, Candidate] {
-
- def feature: Feature[Query, FeatureValue]
-
- override def apply(query: Query): Seq[Candidate] =
- query.features.map(featureMap => transform(featureMap.get(feature))).getOrElse(Seq.empty)
-
- def transform(featureValue: FeatureValue): Seq[Candidate]
-}
-
-/**
- * Retrieve Candidates from a [[Feature]] on the [[PipelineQuery]]'s FeatureMap. This extractor can
- * be used with a single [[Feature]] if the Feature value and the Seq of [[Candidate]] types match.
- */
-case class CandidateQueryFeatureCandidateExtractor[-Query <: PipelineQuery, Candidate](
- override val feature: Feature[Query, Seq[Candidate]])
- extends QueryFeatureCandidateExtractor[Query, Seq[Candidate], Candidate] {
-
- override def transform(featureValue: Seq[Candidate]): Seq[Candidate] = featureValue
-}
-
-/**
- * A [[CandidateSource]] that retrieves candidates from the Request via a [[CandidateExtractor]]
- */
-case class PassthroughCandidateSource[-Request, +Candidate](
- override val identifier: CandidateSourceIdentifier,
- candidateExtractor: CandidateExtractor[Request, Candidate])
- extends CandidateSource[Request, Candidate] {
-
- def apply(query: Request): Stitch[Seq[Candidate]] = Stitch.value(candidateExtractor(query))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala
deleted file mode 100644
index 7a1f3d4dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.stitch.Stitch
-
-/**
- * A [[CandidateSource]] that always returns [[result]] regardless of the input
- */
-case class StaticCandidateSource[Candidate](
- override val identifier: CandidateSourceIdentifier,
- result: Seq[Candidate])
- extends CandidateSource[Any, Candidate] {
-
- def apply(request: Any): Stitch[Seq[Candidate]] = Stitch.value(result)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD
deleted file mode 100644
index f0cc41a88..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala
deleted file mode 100644
index 646b09928..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.product_pipeline
-
-import com.google.inject.Provider
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.configapi.ParamsBuilder
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest
-import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry
-import com.twitter.stitch.Stitch
-import scala.reflect.runtime.universe._
-
-/**
- * A [[CandidateSource]] for getting candidates from a different
- * [[com.twitter.product_mixer.core.model.marshalling.request.Product]] within the same Product
- * Mixer-based service. This is useful when calling a RecommendationPipeline-based Product from a
- * MixerPipeline-based Product. In this scenario, the two Products can remain
- * independent and encapsulated within the Product Mixer service, which provides future optionality
- * for migrating one of the two products into a new Product Mixer-based service based on the
- * scaling needs.
- *
- * @tparam Query [[PipelineQuery]] from the originating Product
- * @tparam MixerRequest the [[Request]] domain model for the Product Mixer service. Adds a Context
- * bound (syntactic sugar) to add TypeTag to implicit scope for
- * [[ProductPipelineRegistry.getProductPipeline()]]. Note that `trait` does not
- * support context bounds, so this abstraction is expressed as an
- * `abstract class`.
- * @tparam ProductPipelineResult the return type of the candidate source Product. Adds a Context
- * bound (syntactic sugar) to add TypeTag to implicit scope for
- * [[ProductPipelineRegistry.getProductPipeline()]]
- * @tparam Candidate the type of candidate returned by this candidate source, which is typically
- * extracted from within the ProductPipelineResult type
- */
-abstract class ProductPipelineCandidateSource[
- -Query <: PipelineQuery,
- MixerRequest <: Request: TypeTag,
- ProductPipelineResult: TypeTag,
- +Candidate]
- extends CandidateSource[Query, Candidate] {
-
- /**
- * @note Define as a Guice [[Provider]] in order to break the circular injection dependency
- */
- val productPipelineRegistry: Provider[ProductPipelineRegistry]
-
- /**
- * @note Define as a Guice [[Provider]] in order to break the circular injection dependency
- */
- val paramsBuilder: Provider[ParamsBuilder]
-
- def pipelineRequestTransformer(currentPipelineQuery: Query): MixerRequest
-
- def productPipelineResultTransformer(productPipelineResult: ProductPipelineResult): Seq[Candidate]
-
- override def apply(query: Query): Stitch[Seq[Candidate]] = {
- val request = pipelineRequestTransformer(query)
-
- val params = paramsBuilder
- .get().build(
- clientContext = request.clientContext,
- product = request.product,
- featureOverrides = request.debugParams.flatMap(_.featureOverrides).getOrElse(Map.empty)
- )
-
- productPipelineRegistry
- .get()
- .getProductPipeline[MixerRequest, ProductPipelineResult](request.product)
- .process(ProductPipelineRequest(request, params))
- .map(productPipelineResultTransformer)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD
deleted file mode 100644
index 24dea9785..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "stitch/stitch-core",
- "strato/src/main/scala/com/twitter/strato/catalog",
- "strato/src/main/scala/com/twitter/strato/client",
- "strato/src/main/scala/com/twitter/strato/response",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "stitch/stitch-core",
- "strato/src/main/scala/com/twitter/strato/catalog",
- "strato/src/main/scala/com/twitter/strato/client",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala
deleted file mode 100644
index 4e72f1c44..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.Unauthorized
-import com.twitter.stitch.Stitch
-import com.twitter.strato.response.Err
-
-/**
- * Categorize Strato's Err messages to our PipelineFailures.
- *
- * This should be used by all strato-based candidate source, and we can
- * add more cases here as they're useful.
- */
-object StratoErrCategorizer {
- val CategorizeStratoException: PartialFunction[Throwable, Stitch[Nothing]] = {
- case err @ Err(Err.Authorization, reason, context) =>
- Stitch.exception(
- PipelineFailure(Unauthorized, s"$reason [${context.toString}]", underlying = Some(err))
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala
deleted file mode 100644
index 19c8a6dba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[Unit]] and the Value is a Seq of [[StratoResult]]
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoResult the column's Value's Seq type
- */
-trait StratoKeyFetcherSeqSource[StratoKey, StratoResult]
- extends CandidateSource[StratoKey, StratoResult] {
-
- val fetcher: Fetcher[StratoKey, Unit, Seq[StratoResult]]
-
- override def apply(key: StratoKey): Stitch[Seq[StratoResult]] = {
- fetcher
- .fetch(key)
- .map { result =>
- result.v
- .getOrElse(Seq.empty)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala
deleted file mode 100644
index 9d3f0e113..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[Unit]] and the Value is a [[StratoValue]]
- *
- * A `stratoResultTransformer` must be defined to convert the [[StratoValue]] into a Seq of [[Candidate]]
- *
- * If you need to extract features from the [[StratoValue]] (like a cursor),
- * use [[StratoKeyFetcherWithSourceFeaturesSource]] instead.
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoValue the column's Value type
- */
-trait StratoKeyFetcherSource[StratoKey, StratoValue, Candidate]
- extends CandidateSource[StratoKey, Candidate] {
-
- val fetcher: Fetcher[StratoKey, Unit, StratoValue]
-
- /**
- * Transforms the value type returned by Strato into a Seq[Candidate].
- *
- * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate.
- *
- * Often, it just extracts a Seq from within a larger wrapper object.
- *
- * If there is global metadata that you need to include, you can zip it with the candidates,
- * returning something like Seq((candiate, metadata), (candidate, metadata)) etc.
- */
- protected def stratoResultTransformer(stratoResult: StratoValue): Seq[Candidate]
-
- override def apply(key: StratoKey): Stitch[Seq[Candidate]] = {
- fetcher
- .fetch(key)
- .map { result =>
- result.v
- .map(stratoResultTransformer)
- .getOrElse(Seq.empty)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala
deleted file mode 100644
index d868d2862..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[Unit]] and the Value is a [[StratoValue]]
- *
- * A [[stratoResultTransformer]] must be defined to convert the
- * [[StratoValue]] into a Seq of [[Candidate]]
- *
- * A [[extractFeaturesFromStratoResult]] must be defined to extract a
- * [[FeatureMap]] from the [[StratoValue]]. If you don't need to do that,
- * use a [[StratoKeyFetcherSource]] instead.
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoValue the column's Value type
- */
-trait StratoKeyFetcherWithSourceFeaturesSource[StratoKey, StratoValue, Candidate]
- extends CandidateSourceWithExtractedFeatures[StratoKey, Candidate] {
-
- val fetcher: Fetcher[StratoKey, Unit, StratoValue]
-
- /**
- * Transforms the value type returned by Strato into a Seq[Candidate].
- *
- * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate.
- *
- * Often, it just extracts a Seq from within a larger wrapper object.
- *
- * If there is global metadata that you need to include, see [[extractFeaturesFromStratoResult]]
- * below to put that into a Feature.
- */
- protected def stratoResultTransformer(stratoResult: StratoValue): Seq[Candidate]
-
- /***
- * Transforms the value type returned by Strato into a FeatureMap.
- *
- * Override this to extract global metadata like cursors and place the results
- * into a Feature.
- *
- * For example, a cursor.
- */
- protected def extractFeaturesFromStratoResult(stratoResult: StratoValue): FeatureMap
-
- override def apply(key: StratoKey): Stitch[CandidatesWithSourceFeatures[Candidate]] = {
- fetcher
- .fetch(key)
- .map { result =>
- val candidates = result.v
- .map(stratoResultTransformer)
- .getOrElse(Seq.empty)
-
- val features = result.v
- .map(extractFeaturesFromStratoResult)
- .getOrElse(FeatureMap.empty)
-
- CandidatesWithSourceFeatures(candidates, features)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala
deleted file mode 100644
index 564ea253c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-/** Represents a Strato column's Key and View arguments */
-case class StratoKeyView[StratoKey, StratoView](key: StratoKey, view: StratoView)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala
deleted file mode 100644
index f1bcddbd3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[StratoView]] and the Value is a Seq of [[StratoResult]]
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoView the column's View type
- * @tparam StratoResult the column's Value's Seq type
- */
-trait StratoKeyViewFetcherSeqSource[StratoKey, StratoView, StratoResult]
- extends CandidateSource[StratoKeyView[StratoKey, StratoView], StratoResult] {
-
- val fetcher: Fetcher[StratoKey, StratoView, Seq[StratoResult]]
-
- override def apply(
- request: StratoKeyView[StratoKey, StratoView]
- ): Stitch[Seq[StratoResult]] = {
- fetcher
- .fetch(request.key, request.view)
- .map { result =>
- result.v
- .getOrElse(Seq.empty)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala
deleted file mode 100644
index 718dc632a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[StratoView]] and the Value is a [[StratoValue]]
- *
- * A `stratoResultTransformer` must be defined to convert the [[StratoValue]] into a Seq of [[Candidate]]
- *
- * If you need to extract features from the [[StratoValue]] (like a cursor),
- * use [[StratoKeyViewFetcherWithSourceFeaturesSource]] instead.
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoView the column's View type
- * @tparam StratoValue the column's Value type
- */
-trait StratoKeyViewFetcherSource[StratoKey, StratoView, StratoValue, Candidate]
- extends CandidateSource[StratoKeyView[StratoKey, StratoView], Candidate] {
-
- val fetcher: Fetcher[StratoKey, StratoView, StratoValue]
-
- /**
- * Transforms the value type returned by Strato into a Seq[Candidate].
- *
- * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate.
- *
- * Often, it just extracts a Seq from within a larger wrapper object.
- *
- * If there is global metadata that you need to include, you can zip it with the candidates,
- * returning something like Seq((candiate, metadata), (candidate, metadata)) etc.
- */
- protected def stratoResultTransformer(
- stratoKey: StratoKey,
- stratoResult: StratoValue
- ): Seq[Candidate]
-
- override def apply(
- request: StratoKeyView[StratoKey, StratoView]
- ): Stitch[Seq[Candidate]] = {
- fetcher
- .fetch(request.key, request.view)
- .map { result =>
- result.v
- .map((stratoResult: StratoValue) => stratoResultTransformer(request.key, stratoResult))
- .getOrElse(Seq.empty)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala
deleted file mode 100644
index 65678a14c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.candidate_source.strato
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.stitch.Stitch
-import com.twitter.strato.client.Fetcher
-
-/**
- * A [[CandidateSource]] for getting Candidates from Strato where the
- * Strato column's View is [[StratoView]] and the Value is a [[StratoValue]]
- *
- * A [[stratoResultTransformer]] must be defined to convert the
- * [[StratoValue]] into a Seq of [[Candidate]]
- *
- * [[extractFeaturesFromStratoResult]] must be defined to extract a
- * [[FeatureMap]] from the [[StratoValue]]. If you don't need to do that,
- * use a [[StratoKeyViewFetcherSource]] instead.
- *
- * @tparam StratoKey the column's Key type
- * @tparam StratoView the column's View type
- * @tparam StratoValue the column's Value type
- */
-trait StratoKeyViewFetcherWithSourceFeaturesSource[StratoKey, StratoView, StratoValue, Candidate]
- extends CandidateSourceWithExtractedFeatures[StratoKeyView[StratoKey, StratoView], Candidate] {
-
- val fetcher: Fetcher[StratoKey, StratoView, StratoValue]
-
- /**
- * Transforms the value type returned by Strato into a Seq[Candidate].
- *
- * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate.
- *
- * Often, it just extracts a Seq from within a larger wrapper object.
- *
- * If there is global metadata that you need to include, see [[extractFeaturesFromStratoResult]]
- * below to put that into a Feature.
- */
- protected def stratoResultTransformer(
- stratoKey: StratoKey,
- stratoResult: StratoValue
- ): Seq[Candidate]
-
- /**
- * Transforms the value type returned by Strato into a FeatureMap.
- *
- * Override this to extract global metadata like cursors and place the results
- * into a Feature.
- *
- * For example, a cursor.
- */
- protected def extractFeaturesFromStratoResult(
- stratoKey: StratoKey,
- stratoResult: StratoValue
- ): FeatureMap
-
- override def apply(
- request: StratoKeyView[StratoKey, StratoView]
- ): Stitch[CandidatesWithSourceFeatures[Candidate]] = {
- fetcher
- .fetch(request.key, request.view)
- .map { result =>
- val candidates = result.v
- .map((stratoResult: StratoValue) => stratoResultTransformer(request.key, stratoResult))
- .getOrElse(Seq.empty)
-
- val features = result.v
- .map((stratoResult: StratoValue) =>
- extractFeaturesFromStratoResult(request.key, stratoResult))
- .getOrElse(FeatureMap.empty)
-
- CandidatesWithSourceFeatures(candidates, features)
- }.rescue(StratoErrCategorizer.CategorizeStratoException)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD
deleted file mode 100644
index c0bae6c88..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala
deleted file mode 100644
index b01d0207b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines
-
-/**
- * Specifies whether a function component (e.g, [[Gate]] or [[Selector]])
- * should apply to a given [[CandidateWithDetails]]
- */
-sealed trait CandidateScope {
-
- /**
- * returns True if the provided `candidate` is in scope
- */
- def contains(candidate: CandidateWithDetails): Boolean
-
- /** partitions `candidates` into those that this scope [[contains]] and those it does not */
- final def partition(
- candidates: Seq[CandidateWithDetails]
- ): CandidateScope.PartitionedCandidates = {
- val (candidatesInScope, candidatesOutOfScope) = candidates.partition(contains)
- CandidateScope.PartitionedCandidates(candidatesInScope, candidatesOutOfScope)
- }
-}
-
-object CandidateScope {
- case class PartitionedCandidates(
- candidatesInScope: Seq[CandidateWithDetails],
- candidatesOutOfScope: Seq[CandidateWithDetails])
-}
-
-/**
- * A [[CandidateScope]] that applies the given functional component
- * to all candidates regardless of which pipeline is their [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]].
- */
-case object AllPipelines extends CandidateScope {
- override def contains(candidate: CandidateWithDetails): Boolean = true
-}
-
-/**
- * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]]
- * only to candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines]]
- * has an Identifier in the [[pipelines]] Set.
- * In most cases where candidates are not pre-merged, the Set contains the candidate pipeline identifier the candidate
- * came from. In the case where a candidate's feature maps were merged using [[CombineFeatureMapsCandidateMerger]], the
- * set contains all candidate pipelines the merged candidate came from and this scope will include the candidate if any
- * of the pipelines match.
- */
-case class SpecificPipelines(pipelines: Set[CandidatePipelineIdentifier]) extends CandidateScope {
-
- require(
- pipelines.nonEmpty,
- "Expected `SpecificPipelines` have a non-empty Set of CandidatePipelineIdentifiers.")
-
- override def contains(candidate: CandidateWithDetails): Boolean = {
- candidate.features.get(CandidatePipelines).exists(pipelines.contains)
- }
-}
-
-/**
- * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]]
- * only to candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]]
- * is [[pipeline]].
- */
-case class SpecificPipeline(pipeline: CandidatePipelineIdentifier) extends CandidateScope {
-
- override def contains(candidate: CandidateWithDetails): Boolean = candidate.features
- .get(CandidatePipelines).contains(pipeline)
-}
-
-object SpecificPipelines {
- def apply(
- pipeline: CandidatePipelineIdentifier,
- pipelines: CandidatePipelineIdentifier*
- ): CandidateScope = {
- if (pipelines.isEmpty)
- SpecificPipeline(pipeline)
- else
- SpecificPipelines((pipeline +: pipelines).toSet)
- }
-}
-
-/**
- * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]]
- * to all candidates except for the candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines]]
- * has an Identifier in the [[pipelinesToExclude]] Set.
- * In most cases where candidates are not pre-merged, the Set contains the candidate pipeline identifier the candidate
- * came from. In the case where a candidate's feature maps were merged using [[CombineFeatureMapsCandidateMerger]], the
- * set contains all candidate pipelines the merged candidate came from and this scope will include the candidate if any
- * of the pipelines match.
- */
-case class AllExceptPipelines(
- pipelinesToExclude: Set[CandidatePipelineIdentifier])
- extends CandidateScope {
- override def contains(candidate: CandidateWithDetails): Boolean = !candidate.features
- .get(CandidatePipelines).exists(pipelinesToExclude.contains)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala
deleted file mode 100644
index 4a1d9d11c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.access_policy
-
-import com.fasterxml.jackson.annotation.JsonSubTypes
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-
-/**
- * The Access Policy to set for gating querying in the turntable tool.
- *
- * @note implementations must be simple case classes with unique structures for serialization
- */
-@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
-@JsonSubTypes(
- Array(
- new JsonSubTypes.Type(value = classOf[AllowedLdapGroups], name = "AllowedLdapGroups"),
- new JsonSubTypes.Type(value = classOf[BlockEverything], name = "BlockEverything")
- )
-)
-sealed trait AccessPolicy
-
-/**
- * Users must be in *at least* one of the provided LDAP groups in order to make a query.
- *
- * @param groups LDAP groups allowed to access this product
- */
-case class AllowedLdapGroups(groups: Set[String]) extends AccessPolicy
-
-object AllowedLdapGroups {
- def apply(group: String): AllowedLdapGroups = AllowedLdapGroups(Set(group))
-}
-
-/**
- * Block all requests to a product.
- *
- * @note this needs to be a case class rather than an object because classOf doesn't work on objects
- * and JsonSubTypes requires the annotation argument to be a constant (ruling out .getClass).
- * This issue may be resolved in Scala 2.13: https://github.com/scala/scala/pull/9279
- */
-case class BlockEverything() extends AccessPolicy
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala
deleted file mode 100644
index eaaa24fac..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.access_policy
-
-/**
- * Controls how access policies are applied to allow/reject a request
- */
-object AccessPolicyEvaluator {
- def evaluate(productAccessPolicies: Set[AccessPolicy], userLdapGroups: Set[String]): Boolean =
- productAccessPolicies.exists {
- case AllowedLdapGroups(allowedGroups) => allowedGroups.exists(userLdapGroups.contains)
- case _: BlockEverything => false
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD
deleted file mode 100644
index 0c605fff9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- ],
- exports = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala
deleted file mode 100644
index 52322802c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.access_policy
-
-import com.twitter.product_mixer.core.model.common.Component
-
-private[core] trait WithDebugAccessPolicies { self: Component =>
-
- /** The [[AccessPolicy]]s that will be used for this component in turntable & other debug tooling
- * to execute arbitrary queries against the component */
- val debugAccessPolicies: Set[AccessPolicy] = Set.empty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala
deleted file mode 100644
index b22a566a6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate
-
-/**
- * [[Alert]]s will trigger notifications to their [[NotificationGroup]]
- * when the [[Predicate]]s are triggered.
- */
-trait Alert {
-
- /** A group of alert levels and where the alerts for those levels should be sent */
- val notificationGroup: NotificationGroup
-
- /** Predicate indicating that the component is in a degraded state */
- val warnPredicate: Predicate
-
- /** Predicate indicating that the component is not functioning correctly */
- val criticalPredicate: Predicate
-
- /** An optional link to the runbook detailing how to respond to this alert */
- val runbookLink: Option[String]
-
- /** Indicates which metrics this [[Alert]] is for */
- val alertType: AlertType
-
- /** Where the metrics are from, @see [[Source]] */
- val source: Source = Server()
-
- /** A suffix to add to the end of the metric, this is often a [[Percentile]] */
- val metricSuffix: Option[String] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala
deleted file mode 100644
index 58ae57b8a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-/**
- * [[AlertType]] is used to indicate which metric an alert is for
- *
- * @note adding new [[AlertType]]s requires updating the dashboard generation code
- */
-sealed trait AlertType { val metricType: String }
-
-/** Monitors the latency */
-case object Latency extends AlertType { override val metricType: String = "Latency" }
-
-/** Monitors the success rate __excluding__ client failures */
-case object SuccessRate extends AlertType { override val metricType: String = "SuccessRate" }
-
-/** Monitors the throughput */
-case object Throughput extends AlertType { override val metricType: String = "Throughput" }
-
-/** Monitors the empty response rate */
-case object EmptyResponseRate extends AlertType {
- override val metricType: String = "EmptyResponseRate"
-}
-
-/** Monitors the empty response size */
-case object ResponseSize extends AlertType { override val metricType: String = "ResponseSize" }
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD
deleted file mode 100644
index bfdea7743..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "3rdparty/jvm/javax/inject:javax.inject",
- "3rdparty/jvm/javax/mail",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate",
- "strato/src/main/scala/com/twitter/strato/catalog",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate",
- "strato/src/main/scala/com/twitter/strato/catalog",
- "util/util-core:scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala
deleted file mode 100644
index d937abd80..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfAbove
-
-/**
- * [[EmptyResponseRateAlert]] triggers when the percentage of requests with empty responses (defined
- * as the number of items returned excluding cursors) rises above the [[TriggerIfAbove]] threshold
- * for a configured amount of time.
- *
- * @note EmptyResponseRate thresholds must be between 0 and 100%
- */
-case class EmptyResponseRateAlert(
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: TriggerIfAbove,
- override val criticalPredicate: TriggerIfAbove,
- override val runbookLink: Option[String] = None)
- extends Alert {
- override val alertType: AlertType = EmptyResponseRate
- require(
- warnPredicate.threshold > 0 && warnPredicate.threshold <= 100,
- s"EmptyResponseRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}"
- )
- require(
- criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100,
- s"EmptyResponseRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}"
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala
deleted file mode 100644
index a8a7c91ba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfLatencyAbove
-
-/**
- * Similar to [[LatencyAlert]] but intended for use with an external client calling Product Mixer.
- *
- * [[GenericClientLatencyAlert]] triggers when the Latency for the specified client
- * rises above the [[TriggerIfLatencyAbove]] threshold for the configured amount of time.
- */
-case class GenericClientLatencyAlert(
- override val source: GenericClient,
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: TriggerIfLatencyAbove,
- override val criticalPredicate: TriggerIfLatencyAbove,
- override val runbookLink: Option[String] = None)
- extends Alert {
- override val alertType: AlertType = Latency
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala
deleted file mode 100644
index 27c03a2f9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfBelow
-
-/**
- * Similar to [[SuccessRateAlert]] but intended for use with an external client calling Product Mixer
- *
- * [[GenericClientSuccessRateAlert]] triggers when the Success Rate for the external client
- * drops below the [[TriggerIfBelow]] threshold for the configured amount of time
- *
- * @note SuccessRate thresholds must be between 0 and 100%
- */
-case class GenericClientSuccessRateAlert(
- override val source: GenericClient,
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: TriggerIfBelow,
- override val criticalPredicate: TriggerIfBelow,
- override val runbookLink: Option[String] = None)
- extends Alert {
- override val alertType: AlertType = SuccessRate
- require(
- warnPredicate.threshold > 0 && warnPredicate.threshold <= 100,
- s"SuccessRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}"
- )
- require(
- criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100,
- s"SuccessRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}"
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala
deleted file mode 100644
index e69b226d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate
-
-/**
- * Similar to [[ThroughputAlert]] but intended for an external client calling Product Mixer.
- *
- * [[GenericClientThroughputAlert]] triggers when the requests/sec for the external client
- * is outside of the predicate set by a [[ThroughputPredicate]] for the configured amount of time
- */
-case class GenericClientThroughputAlert(
- override val source: GenericClient,
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: ThroughputPredicate,
- override val criticalPredicate: ThroughputPredicate,
- override val runbookLink: Option[String] = None)
- extends Alert {
- override val alertType: AlertType = Throughput
- require(
- warnPredicate.threshold >= 0,
- s"ThroughputAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}")
- require(
- criticalPredicate.threshold >= 0,
- s"ThroughputAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}")
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala
deleted file mode 100644
index 08fe3f459..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-/**
- * Indicates that an [[Alert]] can be passed to [[StratoColumnAlert]]. Not all [[Alert]]s can be
- * Strato alerts since our ability to observe from Strato's perspective is limited by the available
- * metrics.
- *
- * @note can only be used in conjunction with [[Alert]]
- */
-trait IsObservableFromStrato { _: Alert => }
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala
deleted file mode 100644
index 47819f2d0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfLatencyAbove
-
-/**
- * [[GenericClientLatencyAlert]] triggers when the Latency for the component this is used with
- * rises above the [[TriggerIfLatencyAbove]] threshold for the configured amount of time
- */
-case class LatencyAlert(
- override val notificationGroup: NotificationGroup,
- percentile: Percentile,
- override val warnPredicate: TriggerIfLatencyAbove,
- override val criticalPredicate: TriggerIfLatencyAbove,
- override val runbookLink: Option[String] = None)
- extends Alert
- with IsObservableFromStrato {
- override val alertType: AlertType = Latency
-
- override val metricSuffix: Option[String] = Some(percentile.metricSuffix)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala
deleted file mode 100644
index 400c122c8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.util.Try
-import javax.mail.internet.InternetAddress
-
-/**
- * Destination represents the place to which alerts will be sent. Often you will only need one field
- * populated (either a Pager Duty key or a list of emails).
- *
- * See the Monitoring 2.0 docs for more information on [[https://docbird.twitter.biz/mon/how-to-guides.html?highlight=notificationgroup#set-up-email-pagerduty-and-slack-notifications setting up a Pager Duty rotation]]
- */
-case class Destination(
- pagerDutyKey: Option[String] = None,
- emails: Seq[String] = Seq.empty) {
-
- require(
- pagerDutyKey.forall(_.length == 32),
- s"Expected `pagerDutyKey` to be 32 characters long but got `$pagerDutyKey`")
- emails.foreach { email =>
- require(
- Try(new InternetAddress(email).validate()).isReturn,
- s"Expected only valid email addresses but got an invalid email address: `$email`")
- }
- require(
- pagerDutyKey.nonEmpty || emails.nonEmpty,
- s"Expected a `pagerDutyKey` or at least 1 email address but got neither")
-}
-
-/**
- * NotificationGroup maps alert levels to destinations. Having different destinations based on the
- * urgency of the alert can sometimes be useful. For example, you could have a daytime on-call for
- * warn alerts and a 24 on-call for critical alerts.
- */
-case class NotificationGroup(
- critical: Destination,
- warn: Destination)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala
deleted file mode 100644
index f2961b8bc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-/**
- * [[Percentile]] is the specific metric that should be monitored.
- * Some metrics such as Latency are recorded using [[https://twitter.github.io/util/docs/com/twitter/finagle/stats/Stat.html Stats]]
- * the stats are recorded as various percentiles such as `my/stat.p95` or `my/stat.min`.
- */
-sealed trait Percentile { val metricSuffix: String }
-case object Min extends Percentile { override val metricSuffix: String = ".min" }
-case object Avg extends Percentile { override val metricSuffix: String = ".avg" }
-case object P50 extends Percentile { override val metricSuffix: String = ".p50" }
-case object P90 extends Percentile { override val metricSuffix: String = ".p90" }
-case object P95 extends Percentile { override val metricSuffix: String = ".p95" }
-case object P99 extends Percentile { override val metricSuffix: String = ".p99" }
-case object P999 extends Percentile { override val metricSuffix: String = ".p9990" }
-case object P9999 extends Percentile { override val metricSuffix: String = ".p9999" }
-case object Max extends Percentile { override val metricSuffix: String = ".max" }
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala
deleted file mode 100644
index 263354c24..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate
-
-/**
- * [[ResponseSizeAlert]] triggers when the specified percentile of requests with empty responses (defined
- * as the number of items returned excluding cursors) is beyond the [[ThroughputPredicate]] threshold
- * for a configured amount of time.
- */
-case class ResponseSizeAlert(
- override val notificationGroup: NotificationGroup,
- percentile: Percentile,
- override val warnPredicate: ThroughputPredicate,
- override val criticalPredicate: ThroughputPredicate,
- override val runbookLink: Option[String] = None)
- extends Alert {
- override val metricSuffix: Option[String] = Some(percentile.metricSuffix)
- override val alertType: AlertType = ResponseSize
- require(
- warnPredicate.threshold >= 0,
- s"ResponseSizeAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}"
- )
- require(
- criticalPredicate.threshold >= 0,
- s"ResponseSizeAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}"
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala
deleted file mode 100644
index 3e961c561..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.fasterxml.jackson.annotation.JsonSubTypes
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-
-/**
- * where the metric originates from, such as from the server or from a client
- *
- * @note implementations must be simple case classes with unique structures for serialization
- */
-@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
-@JsonSubTypes(
- Array(
- new JsonSubTypes.Type(value = classOf[Server], name = "Server"),
- new JsonSubTypes.Type(value = classOf[Strato], name = "Strato"),
- new JsonSubTypes.Type(value = classOf[GenericClient], name = "GenericClient")
- )
-)
-sealed trait Source
-
-/** metrics for the Product Mixer server */
-case class Server() extends Source
-
-/** metrics from the perspective of a Strato column */
-case class Strato(stratoColumnPath: String, stratoColumnOp: String) extends Source
-
-/**
- * metrics from the perspective of a generic client
- *
- * @param displayName human readable name for the client
- * @param service service referenced in the query, of the form ..
- * @param metricSource the source of the metric query, usually of the form sd...
- * @param failureMetric the name of the metric indicating a client failure
- * @param requestMetric the name of the metric indicating a request has been made
- * @param latencyMetric the name of the metric measuring a request's latency
- *
- * @note We strongly recommend the use of [[Strato]] where possible. [[GenericClient]] is provided as a
- * catch-all source for teams that have unusual legacy call paths (such as Macaw).
- */
-case class GenericClient(
- displayName: String,
- service: String,
- metricSource: String,
- failureMetric: String,
- requestMetric: String,
- latencyMetric: String)
- extends Source
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala
deleted file mode 100644
index 7f000e039..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate
-import com.twitter.strato.catalog.OpTag
-
-/**
- * triggers when the a Strato column's is outside of the predicate set by the provided [[Alert]]
- *
- * @note the [[Alert]] passed into a [[StratoColumnAlert]]
- * can not be a [[StratoColumnAlert]]
- */
-case class StratoColumnAlert(column: String, op: OpTag, alert: Alert with IsObservableFromStrato)
- extends Alert {
-
- override val source: Source = Strato(column, op.tag)
- override val notificationGroup: NotificationGroup = alert.notificationGroup
- override val warnPredicate: Predicate = alert.warnPredicate
- override val criticalPredicate: Predicate = alert.criticalPredicate
- override val runbookLink: Option[String] = alert.runbookLink
- override val alertType: AlertType = alert.alertType
- override val metricSuffix: Option[String] = alert.metricSuffix
-}
-
-object StratoColumnAlerts {
-
- /** Make a seq of Alerts for the provided Strato column */
- def apply(
- column: String,
- op: OpTag,
- alerts: Seq[Alert with IsObservableFromStrato]
- ): Seq[Alert] = {
- alerts.map(StratoColumnAlert(column, op, _))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala
deleted file mode 100644
index f8ccbf8a2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfBelow
-
-/**
- * [[SuccessRateAlert]] triggers when the Success Rate for the component this is used
- * with drops below the [[TriggerIfBelow]] threshold for the configured amount of time
- *
- * @note SuccessRate thresholds must be between 0 and 100%
- */
-case class SuccessRateAlert(
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: TriggerIfBelow,
- override val criticalPredicate: TriggerIfBelow,
- override val runbookLink: Option[String] = None)
- extends Alert
- with IsObservableFromStrato {
- override val alertType: AlertType = SuccessRate
- require(
- warnPredicate.threshold > 0 && warnPredicate.threshold <= 100,
- s"SuccessRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}"
- )
- require(
- criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100,
- s"SuccessRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}"
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala
deleted file mode 100644
index d8a947ce1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert
-
-import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate
-
-/**
- * [[ThroughputAlert]] triggers when the requests/sec for the component this is used
- * with is outside of the predicate set by a [[ThroughputPredicate]] for
- * the configured amount of time
- */
-case class ThroughputAlert(
- override val notificationGroup: NotificationGroup,
- override val warnPredicate: ThroughputPredicate,
- override val criticalPredicate: ThroughputPredicate,
- override val runbookLink: Option[String] = None)
- extends Alert
- with IsObservableFromStrato {
- override val alertType: AlertType = Throughput
- require(
- warnPredicate.threshold >= 0,
- s"ThroughputAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}")
- require(
- criticalPredicate.threshold >= 0,
- s"ThroughputAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}")
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD
deleted file mode 100644
index 1aee67e8e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "util/util-core:scala",
- ],
- exports = [
- "util/util-core:scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala
deleted file mode 100644
index c0a6d2a56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-/**
- * Specifies the metric granularity
- *
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]]
- */
-sealed trait MetricGranularity { val unit: String }
-
-/**
- * Use minutely metrics and have alert durations in terms of minutes
- *
- * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10
- * then the alert will trigger if there are at least 5 '''minutely''' metric points that are past the threshold
- * in any 10 '''minute''' period
- */
-case object Minutes extends MetricGranularity { override val unit: String = "m" }
-
-/**
- * Use hourly metrics and have alert durations in terms of hours
- *
- * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10
- * then the alert will trigger if there are at least 5 '''hourly''' metric points that are past the threshold
- * in any 10 '''hour''' period
- */
-case object Hours extends MetricGranularity { override val unit: String = "h" }
-
-/**
- * Use daily metrics and have alert durations in terms of days
- *
- * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10
- * then the alert will trigger if there are at least 5 '''daily''' metric points that are past the threshold
- * in any 10 '''day''' period
- */
-case object Days extends MetricGranularity { override val unit: String = "d" }
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala
deleted file mode 100644
index d3f7dd033..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-/**
- * Used for building [[Predicate]]s
- *
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate OPERATOR]]
- */
-private[alert] sealed trait Operator
-private[alert] case object `>` extends Operator
-private[alert] case object `>=` extends Operator
-private[alert] case object `<` extends Operator
-private[alert] case object `<=` extends Operator
-private[alert] case object `!=` extends Operator
-private[alert] case object `=` extends Operator
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala
deleted file mode 100644
index 5d6ad23fe..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-/**
- * [[Predicate]]s will trigger if the metric's value is past the
- * `threshold` for `datapointsPastThreshold` or more datapoints
- * in a given `duration`
- *
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate Predicate]]
- */
-trait Predicate {
-
- /** @see [[https://docbird.twitter.biz/mon/reference.html#predicate OPERATOR]] */
- val operator: Operator
-
- /** @see [[https://docbird.twitter.biz/mon/reference.html#predicate THRESHOLD]] */
- val threshold: Double
-
- /**
- * The number of datapoints in a given duration beyond the threshold that will trigger an alert
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DATAPOINTS]]
- */
- val datapointsPastThreshold: Int
-
- /**
- * @note if using a [[metricGranularity]] of [[Minutes]] then this must be >= 3
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]]
- */
- val duration: Int
-
- /**
- * Specifies the metric granularity
- * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]]
- */
- val metricGranularity: MetricGranularity
-
- require(
- datapointsPastThreshold > 0,
- s"`datapointsPastThreshold` must be > 0 but got `datapointsPastThreshold` = $datapointsPastThreshold"
- )
-
- require(
- datapointsPastThreshold <= duration,
- s"`datapointsPastThreshold` must be <= than `duration.inMinutes` but got `datapointsPastThreshold` = $datapointsPastThreshold `duration` = $duration"
- )
- require(
- metricGranularity != Minutes || duration >= 3,
- s"Predicate durations must be at least 3 minutes but got $duration"
- )
-}
-
-/** [[ThroughputPredicate]]s are predicates that can trigger when the throughput is too low or high */
-trait ThroughputPredicate extends Predicate
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala
deleted file mode 100644
index 8356a2e18..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-/**
- * A [[Predicate]] that triggers if the metric this is used with rises above
- * the [[threshold]] for [[datapointsPastThreshold]] per [[duration]]
- */
-case class TriggerIfAbove(
- override val threshold: Double,
- override val datapointsPastThreshold: Int = 10,
- override val duration: Int = 15,
- override val metricGranularity: MetricGranularity = Minutes)
- extends Predicate
- with ThroughputPredicate {
- override val operator: Operator = `>`
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala
deleted file mode 100644
index b528c15d6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-/**
- * A [[Predicate]] that triggers if the metric this is used with lowers below
- * the [[threshold]] for [[datapointsPastThreshold]] per [[duration]]
- */
-case class TriggerIfBelow(
- override val threshold: Double,
- override val datapointsPastThreshold: Int = 10,
- override val duration: Int = 15,
- override val metricGranularity: MetricGranularity = Minutes)
- extends Predicate
- with ThroughputPredicate {
- override val operator: Operator = `<`
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala
deleted file mode 100644
index 726e83ed5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.common.alert.predicate
-
-import com.twitter.util.Duration
-
-/**
- * A [[Predicate]] that triggers if the metric this is used with rises above the
- * [[latencyThreshold]] for [[datapointsPastThreshold]] per [[duration]]
- *
- * @note [[latencyThreshold]] must be > 0
- */
-case class TriggerIfLatencyAbove(
- latencyThreshold: Duration,
- override val datapointsPastThreshold: Int = 10,
- override val duration: Int = 15,
- override val metricGranularity: MetricGranularity = Minutes)
- extends Predicate {
- override val threshold: Double = latencyThreshold.inMillis
- override val operator: Operator = `>`
- require(
- latencyThreshold > Duration.Zero,
- s"TriggerIfLatencyAbove thresholds must be greater than 0 but got $latencyThreshold")
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD
deleted file mode 100644
index 5baced00c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-featureswitches:v2",
- "featureswitches/featureswitches-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-featureswitches:v2",
- "featureswitches/featureswitches-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala
deleted file mode 100644
index a805af6b9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi
-
-import com.twitter.product_mixer.core.functional_component.configapi.registry.GlobalParamRegistry
-import com.twitter.product_mixer.core.product.registry.ProductParamRegistry
-import com.twitter.timelines.configapi.CompositeConfig
-import com.twitter.timelines.configapi.Config
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConfigBuilder @Inject() (
- productParamRegistry: ProductParamRegistry,
- globalParamRegistry: GlobalParamRegistry) {
-
- def build(): Config =
- new CompositeConfig(productParamRegistry.build() ++ Seq(globalParamRegistry.build()))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala
deleted file mode 100644
index d1e570b59..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.marshalling.request.ClientContext
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.servo.util.MemoizingStatsReceiver
-import com.twitter.timelines.configapi.Config
-import com.twitter.timelines.configapi.FeatureValue
-import com.twitter.timelines.configapi.Params
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/** Singleton object for building [[Params]] to override */
-@Singleton
-class ParamsBuilder @Inject() (
- config: Config,
- requestContextBuilder: RequestContextBuilder,
- statsReceiver: StatsReceiver) {
-
- private[this] val scopedStatsReceiver =
- new MemoizingStatsReceiver(statsReceiver.scope("configapi"))
-
- def build(
- clientContext: ClientContext,
- product: Product,
- featureOverrides: Map[String, FeatureValue],
- fsCustomMapInput: Map[String, Any] = Map.empty
- ): Params = {
- val requestContext =
- requestContextBuilder.build(clientContext, product, featureOverrides, fsCustomMapInput)
-
- config(requestContext, scopedStatsReceiver)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala
deleted file mode 100644
index 82bcbb92f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi
-
-import com.twitter.timelines.configapi.BaseRequestContext
-import com.twitter.timelines.configapi.FeatureContext
-import com.twitter.timelines.configapi.GuestId
-import com.twitter.timelines.configapi.UserId
-import com.twitter.timelines.configapi.WithFeatureContext
-import com.twitter.timelines.configapi.WithGuestId
-import com.twitter.timelines.configapi.WithUserId
-
-/** Represents [[com.twitter.timelines.configapi]]'s context information */
-case class RequestContext(
- userId: Option[UserId],
- guestId: Option[GuestId],
- featureContext: FeatureContext)
- extends BaseRequestContext
- with WithUserId
- with WithGuestId
- with WithFeatureContext
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala
deleted file mode 100644
index fe06fbeb6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi
-
-import com.twitter.featureswitches.v2.FeatureSwitches
-import com.twitter.featureswitches.UserAgent
-import com.twitter.featureswitches.{Recipient => FeatureSwitchRecipient}
-import com.twitter.product_mixer.core.model.marshalling.request.ClientContext
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.timelines.configapi.featureswitches.v2.FeatureSwitchResultsFeatureContext
-import com.twitter.timelines.configapi.FeatureContext
-import com.twitter.timelines.configapi.FeatureValue
-import com.twitter.timelines.configapi.ForcedFeatureContext
-import com.twitter.timelines.configapi.OrElseFeatureContext
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Request Context Factory is used to build RequestContext objects which are used
- * by the config api to determine the param overrides to apply to the request.
- * The param overrides are determined per request by configs which specify which
- * FS/Deciders/AB translate to what param overrides.
- */
-@Singleton
-class RequestContextBuilder @Inject() (featureSwitches: FeatureSwitches) {
-
- /**
- * @param `fsCustomMapInput` allows you to set custom fields on your feature switches.
- * This feature isn't directly supported by product mixer yet, so using this argument
- * will likely result in future cleanup work.
- *
- */
- def build(
- clientContext: ClientContext,
- product: Product,
- featureOverrides: Map[String, FeatureValue],
- fsCustomMapInput: Map[String, Any]
- ): RequestContext = {
- val featureContext =
- getFeatureContext(clientContext, product, featureOverrides, fsCustomMapInput)
-
- RequestContext(clientContext.userId, clientContext.guestId, featureContext)
- }
-
- private[configapi] def getFeatureContext(
- clientContext: ClientContext,
- product: Product,
- featureOverrides: Map[String, FeatureValue],
- fsCustomMapInput: Map[String, Any]
- ): FeatureContext = {
- val recipient = getFeatureSwitchRecipient(clientContext)
- .withCustomFields("product" -> product.identifier.toString, fsCustomMapInput.toSeq: _*)
-
- val results = featureSwitches.matchRecipient(recipient)
- OrElseFeatureContext(
- ForcedFeatureContext(featureOverrides),
- new FeatureSwitchResultsFeatureContext(results))
- }
-
- private[configapi] def getFeatureSwitchRecipient(
- clientContext: ClientContext
- ): FeatureSwitchRecipient = FeatureSwitchRecipient(
- userId = clientContext.userId,
- userRoles = clientContext.userRoles,
- deviceId = clientContext.deviceId,
- guestId = clientContext.guestId,
- languageCode = clientContext.languageCode,
- countryCode = clientContext.countryCode,
- userAgent = clientContext.userAgent.flatMap(UserAgent.apply),
- isVerified = None,
- clientApplicationId = clientContext.appId,
- isTwoffice = clientContext.isTwoffice
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala
deleted file mode 100644
index 8e29a926f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi
-
-import com.twitter.timelines.configapi.Param
-
-/** A [[Param]] used for constant values where we do not require backing by feature switches or deciders */
-case class StaticParam[ValueType](value: ValueType) extends Param[ValueType](value)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD
deleted file mode 100644
index 3d66cd35c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-decider",
- "servo/decider",
- "util/util-core:util-core-util",
- "util/util-logging",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-decider",
- "servo/decider",
- "util/util-core:util-core-util",
- "util/util-logging",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala
deleted file mode 100644
index 8175508cb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi.registry
-
-/**
- * Register Params that do not relate to a specific product.
- * See [[ParamConfig]] for hooks to register Params based on type.
- */
-trait GlobalParamConfig extends ParamConfig with ParamConfigBuilder
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala
deleted file mode 100644
index 6df7cf35f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi.registry
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.servo.decider.DeciderGateBuilder
-import com.twitter.timelines.configapi.BaseConfigBuilder
-import com.twitter.timelines.configapi.Config
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GlobalParamRegistry @Inject() (
- globalParamConfig: GlobalParamConfig,
- deciderGateBuilder: DeciderGateBuilder,
- statsReceiver: StatsReceiver) {
-
- def build(): Config = {
- val globalConfigs = globalParamConfig.build(deciderGateBuilder, statsReceiver)
-
- BaseConfigBuilder(globalConfigs).build("GlobalParamRegistry")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala
deleted file mode 100644
index 20434dcc6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi.registry
-
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.DefinedFeatureName
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.EnumParamWithFeatureName
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.EnumSeqParamWithFeatureName
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.ValueFeatureName
-import com.twitter.timelines.configapi.decider.HasDecider
-import com.twitter.timelines.configapi.Bounded
-import com.twitter.timelines.configapi.FSName
-import com.twitter.timelines.configapi.HasDurationConversion
-import com.twitter.timelines.configapi.OptionalOverride
-import com.twitter.timelines.configapi.Param
-import com.twitter.util.Duration
-
-/** ParamConfig is used to configure overrides for [[Param]]s of various types */
-trait ParamConfig {
-
- def booleanDeciderOverrides: Seq[Param[Boolean] with HasDecider] = Seq.empty
-
- def booleanFSOverrides: Seq[Param[Boolean] with FSName] = Seq.empty
-
- def optionalBooleanOverrides: Seq[
- (Param[Option[Boolean]], DefinedFeatureName, ValueFeatureName)
- ] = Seq.empty
-
- def enumFSOverrides: Seq[EnumParamWithFeatureName[_ <: Enumeration]] = Seq.empty
-
- def enumSeqFSOverrides: Seq[EnumSeqParamWithFeatureName[_ <: Enumeration]] = Seq.empty
-
- /**
- * Support for non-Duration supplied FS overrides (e.g. `timeFromStringFSOverrides`,
- * `timeFromNumberFSOverrides`, `getBoundedOptionalDurationFromMillisOverrides`) is not provided
- * as Duration is preferred
- */
- def boundedDurationFSOverrides: Seq[
- Param[Duration] with Bounded[Duration] with FSName with HasDurationConversion
- ] = Seq.empty
-
- /** Support for unbounded numeric FS overrides is not provided as bounded is preferred */
- def boundedIntFSOverrides: Seq[Param[Int] with Bounded[Int] with FSName] = Seq.empty
-
- def boundedOptionalIntOverrides: Seq[
- (Param[Option[Int]] with Bounded[Option[Int]], DefinedFeatureName, ValueFeatureName)
- ] = Seq.empty
-
- def intSeqFSOverrides: Seq[Param[Seq[Int]] with FSName] = Seq.empty
-
- def boundedLongFSOverrides: Seq[Param[Long] with Bounded[Long] with FSName] = Seq.empty
-
- def boundedOptionalLongOverrides: Seq[
- (Param[Option[Long]] with Bounded[Option[Long]], DefinedFeatureName, ValueFeatureName)
- ] = Seq.empty
-
- def longSeqFSOverrides: Seq[Param[Seq[Long]] with FSName] = Seq.empty
-
- def longSetFSOverrides: Seq[Param[Set[Long]] with FSName] = Seq.empty
-
- def boundedDoubleFSOverrides: Seq[Param[Double] with Bounded[Double] with FSName] = Seq.empty
-
- def boundedOptionalDoubleOverrides: Seq[
- (Param[Option[Double]] with Bounded[Option[Double]], DefinedFeatureName, ValueFeatureName)
- ] = Seq.empty
-
- def doubleSeqFSOverrides: Seq[Param[Seq[Double]] with FSName] = Seq.empty
-
- def stringFSOverrides: Seq[Param[String] with FSName] = Seq.empty
-
- def stringSeqFSOverrides: Seq[Param[Seq[String]] with FSName] = Seq.empty
-
- def optionalStringOverrides: Seq[(Param[Option[String]], DefinedFeatureName, ValueFeatureName)] =
- Seq.empty
-
- def gatedOverrides: Map[String, Seq[OptionalOverride[_]]] = Map.empty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala
deleted file mode 100644
index 5bb5f1ea7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.configapi.registry
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.logging.Logger
-import com.twitter.servo.decider.DeciderGateBuilder
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil
-import com.twitter.timelines.configapi.OptionalOverride
-import com.twitter.timelines.configapi.decider.DeciderUtils
-
-trait ParamConfigBuilder { paramConfig: ParamConfig =>
-
- /** Builds a Seq of [[OptionalOverride]]s based on the [[paramConfig]] */
- def build(
- deciderGateBuilder: DeciderGateBuilder,
- statsReceiver: StatsReceiver
- ): Seq[OptionalOverride[_]] = {
- val logger = Logger(classOf[ParamConfig])
-
- DeciderUtils.getBooleanDeciderOverrides(deciderGateBuilder, booleanDeciderOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBooleanFSOverrides(booleanFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getOptionalBooleanOverrides(optionalBooleanOverrides: _*) ++
- FeatureSwitchOverrideUtil.getEnumFSOverrides(
- statsReceiver.scope("enumConversion"),
- logger,
- enumFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getEnumSeqFSOverrides(
- statsReceiver.scope("enumSeqConversion"),
- logger,
- enumSeqFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedDurationFSOverrides(boundedDurationFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedIntFSOverrides(boundedIntFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedOptionalIntOverrides(boundedOptionalIntOverrides: _*) ++
- FeatureSwitchOverrideUtil.getIntSeqFSOverrides(intSeqFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedLongFSOverrides(boundedLongFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedOptionalLongOverrides(boundedOptionalLongOverrides: _*) ++
- FeatureSwitchOverrideUtil.getLongSeqFSOverrides(longSeqFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getLongSetFSOverrides(longSetFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedDoubleFSOverrides(boundedDoubleFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getBoundedOptionalDoubleOverrides(
- boundedOptionalDoubleOverrides: _*) ++
- FeatureSwitchOverrideUtil.getDoubleSeqFSOverrides(doubleSeqFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getStringFSOverrides(stringFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getStringSeqFSOverrides(stringSeqFSOverrides: _*) ++
- FeatureSwitchOverrideUtil.getOptionalStringOverrides(optionalStringOverrides: _*) ++
- gatedOverrides.flatMap {
- case (fsName, overrides) => FeatureSwitchOverrideUtil.gatedOverrides(fsName, overrides: _*)
- }.toSeq
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD
deleted file mode 100644
index 4db994de8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD
+++ /dev/null
@@ -1,37 +0,0 @@
-scala_library(
- name = "decoration",
- sources = ["Decoration.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- ],
-)
-
-scala_library(
- sources = [
- "!Decoration.scala",
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ":decoration",
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- ":decoration",
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala
deleted file mode 100644
index 4a6a213b7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * [[CandidateDecorator]] generates a [[com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation]]
- * for Candidates, which encapsulate information about how to present the candidate
- *
- * @see [[https://docbird.twitter.biz/product-mixer/functional-components.html#candidate-decorator]]
- * @see [[com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation]]
- */
-trait CandidateDecorator[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]
- extends Component {
-
- override val identifier: DecoratorIdentifier = CandidateDecorator.DefaultCandidateDecoratorId
-
- /**
- * Given a Seq of `Candidate`, returns a [[Decoration]] for candidates which should be decorated
- *
- * `Candidate`s which aren't decorated can be omitted from the results
- */
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[Decoration]]
-}
-
-object CandidateDecorator {
- private[core] val DefaultCandidateDecoratorId: DecoratorIdentifier =
- DecoratorIdentifier(ComponentIdentifier.BasedOnParentComponent)
-
- /**
- * For use when building a [[CandidateDecorator]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]]
- * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]]
- */
- private[core] def copyWithUpdatedIdentifier[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ](
- decorator: CandidateDecorator[Query, Candidate],
- parentIdentifier: ComponentIdentifier
- ): CandidateDecorator[Query, Candidate] = {
- if (decorator.identifier == DefaultCandidateDecoratorId) {
- new CandidateDecorator[Query, Candidate] {
- override val identifier: DecoratorIdentifier = DecoratorIdentifier(parentIdentifier.name)
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[Decoration]] = decorator.apply(query, candidates)
- }
- } else {
- decorator
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala
deleted file mode 100644
index 74c9121b1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation
-
-/**
- * Decoration associates specific [[UniversalPresentation]] with a candidate
- */
-case class Decoration(
- candidate: UniversalNoun[Any],
- presentation: UniversalPresentation)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD
deleted file mode 100644
index 23bf323c6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala
deleted file mode 100644
index 5ee3d5e25..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.slice.builder
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait CandidateSliceItemBuilder[
- -Query <: PipelineQuery,
- -BuilderInput <: UniversalNoun[Any],
- BuilderOutput <: SliceItem] {
-
- def apply(query: Query, candidate: BuilderInput, featureMap: FeatureMap): BuilderOutput
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD
deleted file mode 100644
index 436d75e75..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-scala_library(
- sources = ["**/*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala
deleted file mode 100644
index f14abc28c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait CandidateUrtEntryBuilder[
- -Query <: PipelineQuery,
- -BuilderInput <: UniversalNoun[Any],
- BuilderOutput <: TimelineEntry] {
-
- def apply(query: Query, candidate: BuilderInput, candidateFeatures: FeatureMap): BuilderOutput
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala
deleted file mode 100644
index 7dbe7f567..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseHorizonIconBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[HorizonIcon]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala
deleted file mode 100644
index 00b4d0454..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.util.Duration
-
-trait BaseDurationBuilder[-Query <: PipelineQuery] {
-
- def apply(query: Query, candidate: ShowAlertCandidate, features: FeatureMap): Option[Duration]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala
deleted file mode 100644
index cb95bf2aa..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseShowAlertColorConfigurationBuilder[-Query <: PipelineQuery] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): ShowAlertColorConfiguration
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala
deleted file mode 100644
index 4f64e37bf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseShowAlertDisplayLocationBuilder[-Query <: PipelineQuery] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): ShowAlertDisplayLocation
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala
deleted file mode 100644
index 1d14099b1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseShowAlertIconDisplayInfoBuilder[-Query <: PipelineQuery] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): Option[ShowAlertIconDisplayInfo]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala
deleted file mode 100644
index af9eb6a7f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseShowAlertNavigationMetadataBuilder[-Query <: PipelineQuery] {
-
- def apply(
- query: Query,
- candidate: ShowAlertCandidate,
- features: FeatureMap
- ): Option[ShowAlertNavigationMetadata]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala
deleted file mode 100644
index 17de7cd81..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert
-
-import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseShowAlertUserIdsBuilder[-Query <: PipelineQuery] {
-
- def apply(query: Query, candidate: ShowAlertCandidate, features: FeatureMap): Option[Seq[Long]]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala
deleted file mode 100644
index 879aa99b0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType
-
-trait BaseTopicDisplayTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: PipelineQuery,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[TopicDisplayType]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala
deleted file mode 100644
index 664a4a14c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType
-
-trait BaseTopicFunctionalityTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: PipelineQuery,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[TopicFunctionalityType]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala
deleted file mode 100644
index 9c8a0e6bc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseEntryIdToReplaceBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[String]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala
deleted file mode 100644
index cae142bdd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TimelinesScoreInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseTimelinesScoreInfoBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[TimelinesScoreInfo]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala
deleted file mode 100644
index c3dc6cfe6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetHighlights
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseTweetHighlightsBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[TweetHighlights]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala
deleted file mode 100644
index 17aada2f8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.user
-
-import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserReactiveTriggers
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseUserReactiveTriggersBuilder[-Query <: PipelineQuery, -Candidate <: BaseUserCandidate] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[UserReactiveTriggers]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala
deleted file mode 100644
index e0c662bcc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseClientEventDetailsBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- /**
- * @return a [[ClientEventDetails]] for the provided [[Candidate]]
- * @see [[ClientEventDetails]]
- */
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[ClientEventDetails]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala
deleted file mode 100644
index 27729a162..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseClientEventInfoBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- /**
- * @return a [[ClientEventInfo]] for the provided [[Candidate]]
- * @see [[ClientEventInfo]]
- */
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap,
- element: Option[String]
- ): Option[ClientEventInfo]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala
deleted file mode 100644
index d1482fcf1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseFeedbackActionInfoBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[FeedbackActionInfo]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala
deleted file mode 100644
index 4470ab3dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): String
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala
deleted file mode 100644
index ad1516aa1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): String
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala
deleted file mode 100644
index 221a9107b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-
-trait BaseUrlBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): Url
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala
deleted file mode 100644
index 673ad7542..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BasePromotedMetadataBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[PromotedMetadata]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala
deleted file mode 100644
index db4238d11..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseRichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala
deleted file mode 100644
index 659d6c401..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[SocialContext]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala
deleted file mode 100644
index f51933456..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidate: Candidate,
- candidateFeatures: FeatureMap
- ): Option[SocialContext]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala
deleted file mode 100644
index 0dc6fe5f9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleStringCenterPlaceholderBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): Map[String, Any]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala
deleted file mode 100644
index d006f1bbb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseStringCenterPlaceholderBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]] {
-
- def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): Map[String, Any]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala
deleted file mode 100644
index df44ce8e9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleDisplayTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleDisplayType
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala
deleted file mode 100644
index f30761822..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleFooter]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala
deleted file mode 100644
index 0e0145f10..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Option[ModuleHeader]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala
deleted file mode 100644
index e1218613f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleHeaderDisplayTypeBuilder[
- -Query <: PipelineQuery,
- -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleHeaderDisplayType
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala
deleted file mode 100644
index 6d2e417c3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleMetadataBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleMetadata
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala
deleted file mode 100644
index 2cdf0c8ff..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseModuleShowMoreBehaviorBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): ModuleShowMoreBehavior
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala
deleted file mode 100644
index bf7bcaba1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait BaseTimelineModuleBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] {
-
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): TimelineModule
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD
deleted file mode 100644
index 5f388dfc5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala
deleted file mode 100644
index 069884466..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.SupportsConditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Hydrate features for a specific candidate
- * e.g. if the candidate is a Tweet then a feature could be whether it's is marked as sensitive
- *
- * @note if you want to conditionally run a [[BaseCandidateFeatureHydrator]] you can use the mixin [[com.twitter.product_mixer.core.model.common.Conditionally]]
- * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use
- * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedCandidateFeatureHydrator]] or
- * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedBulkCandidateFeatureHydrator]]
- */
-sealed trait BaseCandidateFeatureHydrator[
- -Query <: PipelineQuery,
- -Result <: UniversalNoun[Any],
- FeatureType <: Feature[_, _]]
- extends FeatureHydrator[FeatureType]
- with SupportsConditionally[Query]
-
-/**
- * A candidate feature hydrator that provides an implementation for hydrating a single candidate
- * at the time. Product Mixer core takes care of hydrating all your candidates for you by
- * calling this for each candidate. This is useful for Stitch-powered downstream APIs (such
- * as Strato, Gizmoduck, etc) where the API takes a single candidate/key and Stitch handles
- * batching for you.
- *
- * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the
- * [[FeatureMap]] for *all* [[Feature]]s intended to be hydrated.
- * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't
- * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]]
- *
- * @tparam Query The query type
- * @tparam Result The Candidate type
- */
-trait CandidateFeatureHydrator[-Query <: PipelineQuery, -Result <: UniversalNoun[Any]]
- extends BaseCandidateFeatureHydrator[Query, Result, Feature[_, _]] {
-
- override val identifier: FeatureHydratorIdentifier
-
- /** Hydrates a [[FeatureMap]] for a single candidate */
- def apply(query: Query, candidate: Result, existingFeatures: FeatureMap): Stitch[FeatureMap]
-}
-
-/**
- * Hydrate features for a list of candidates
- * e.g. for a list of Tweet candidates, a feature could be the visibility reason whether to show or not show each Tweet
- */
-trait BaseBulkCandidateFeatureHydrator[
- -Query <: PipelineQuery,
- -Result <: UniversalNoun[Any],
- FeatureType <: Feature[_, _]]
- extends BaseCandidateFeatureHydrator[Query, Result, FeatureType] {
-
- /**
- * Hydrates a set of [[FeatureMap]]s for the bulk list of candidates. Every input candidate must
- * have corresponding entry in the returned seq with a feature map.
- */
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Result]]
- ): Stitch[Seq[FeatureMap]]
-}
-
-/**
- * A candidate feature hydrator that allows a user to bulk hydrate features for all candidates
- * at once. This is useful for downstream APIs that take a list of candidates in one go such
- * as feature store or scorers.
- *
- * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the
- * [[FeatureMap]] for *all* [[Feature]]s of *all* candidates intended to be hydrated.
- * An alternative to throwing an exception is per-candidate failure handling (e.g. adding
- * a failed [[Feature]] with `addFailure`, a Try with `add`, or an optional value with `add`
- * using [[FeatureMapBuilder]]).
- * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't
- * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]].
- *
- * @tparam Query The query type
- * @tparam Result The Candidate type
- */
-trait BulkCandidateFeatureHydrator[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends BaseBulkCandidateFeatureHydrator[Query, Candidate, Feature[_, _]] {
- override val identifier: FeatureHydratorIdentifier
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala
deleted file mode 100644
index 62c07353f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.Component
-
-/** Hydrates a [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]] for a given input */
-trait FeatureHydrator[FeatureType <: Feature[_, _]] extends Component {
- def features: Set[FeatureType]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala
deleted file mode 100644
index f78e1135a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-case class HydratorCandidateResult[+Candidate <: UniversalNoun[Any]](
- override val candidate: Candidate,
- override val features: FeatureMap)
- extends CandidateWithFeatures[Candidate]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala
deleted file mode 100644
index e40f1ccb8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.SupportsConditionally
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Hydrate features about the query itself (not about the candidates)
- * e.g. features about the user who is making the request, what country the request originated from, etc.
- *
- * @note [[BaseQueryFeatureHydrator]]s populate [[Feature]]s with last-write-wins semantics for
- * duplicate [[Feature]]s, where the last hydrator to run that populates a [[Feature]] will
- * override any previously run [[BaseQueryFeatureHydrator]]s values for that [[Feature]].
- * In a [[com.twitter.product_mixer.core.pipeline.PipelineConfig PipelineConfig]] this means
- * that the right-most [[BaseQueryFeatureHydrator]] to populate a given [[Feature]] will be
- * the value that is available to use.
- *
- * @note if you want to conditionally run a [[BaseQueryFeatureHydrator]] you can use the mixin [[com.twitter.product_mixer.core.model.common.Conditionally]]
- * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use [[com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.ParamGatedQueryFeatureHydrator]]
- *
- * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the
- * [[FeatureMap]] for the [[Feature]]s that were supposed to be hydrated.
- * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't
- * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]]
- */
-trait BaseQueryFeatureHydrator[-Query <: PipelineQuery, FeatureType <: Feature[_, _]]
- extends FeatureHydrator[FeatureType]
- with SupportsConditionally[Query] {
-
- override val identifier: FeatureHydratorIdentifier
-
- /** Hydrates a [[FeatureMap]] for a given [[Query]] */
- def hydrate(query: Query): Stitch[FeatureMap]
-}
-
-trait QueryFeatureHydrator[-Query <: PipelineQuery]
- extends BaseQueryFeatureHydrator[Query, Feature[_, _]]
-
-/**
- * When an [[AsyncHydrator]] is run it will hydrate features in the background
- * and will make them available starting at the specified point in execution.
- *
- * When `hydrateBefore` is reached, any duplicate [[Feature]]s that were already hydrated will be
- * overridden with the new value from the [[AsyncHydrator]]
- *
- * @note [[AsyncHydrator]]s have the same last-write-wins semantics for duplicate [[Feature]]s
- * as [[BaseQueryFeatureHydrator]] but with some nuance. If [[AsyncHydrator]]s for the
- * same [[Feature]] have the same `hydrateBefore` then the right-most [[AsyncHydrator]]s
- * value takes precedence. Similarly, [[AsyncHydrator]]s always hydrate after any other
- * [[BaseQueryFeatureHydrator]]. See the examples for more detail.
- * @example if [[QueryFeatureHydrator]]s that populate the same [[Feature]] are defined in a `PipelineConfig`
- * such as `[ asyncHydratorForFeatureA, normalHydratorForFeatureA ]`, where `asyncHydratorForFeatureA`
- * is an [[AsyncHydrator]], when `asyncHydratorForFeatureA` reaches it's `hydrateBefore`
- * Step in the Pipeline, the value for `FeatureA` from the `asyncHydratorForFeatureA` will override
- * the existing value from `normalHydratorForFeatureA`, even though in the initial `PipelineConfig`
- * they are ordered differently.
- * @example if [[AsyncHydrator]]s that populate the same [[Feature]] are defined in a `PipelineConfig`
- * such as `[ asyncHydratorForFeatureA1, asyncHydratorForFeatureA2 ]`, where both [[AsyncHydrator]]s
- * have the same `hydrateBefore`, when `hydrateBefore` is reached, the value for `FeatureA` from
- * `asyncHydratorForFeatureA2` will override the value from `asyncHydratorForFeatureA1`.
- */
-trait AsyncHydrator {
- _: BaseQueryFeatureHydrator[_, _] =>
-
- /**
- * A [[PipelineStepIdentifier]] from the [[com.twitter.product_mixer.core.pipeline.PipelineConfig]] this is used in
- * by which the [[FeatureMap]] returned by this [[AsyncHydrator]] will be completed.
- *
- * Access to the [[Feature]]s from this [[AsyncHydrator]] prior to reaching the provided
- * [[PipelineStepIdentifier]]s will result in a [[com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException]].
- *
- * @note If [[PipelineStepIdentifier]] is a Step which is run in parallel, the [[Feature]]s will be available for all the parallel Steps.
- */
- def hydrateBefore: PipelineStepIdentifier
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD
deleted file mode 100644
index bd8d63134..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/scala/com/twitter/ml/featurestore/lib/online",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "src/scala/com/twitter/ml/featurestore/lib/online",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala
deleted file mode 100644
index 7b723bdd5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.data.DatasetErrorsById
-import com.twitter.ml.featurestore.lib.data.HydrationError
-import com.twitter.ml.featurestore.lib.dataset.DatasetId
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1Feature
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object FeatureStoreDatasetErrorHandler {
-
- /**
- * This function takes a set of feature store features and constructs a mapping from the underlying
- * feature store dataset back to the features. This is useful for looking up what ProMix features
- * failed based off of a failed feature store dataset at request time. A ProMix feature can be
- * powered by multiple feature store datasets, and conversely, a dataset can be used by many features.
- */
- def datasetToFeaturesMapping[
- Query <: PipelineQuery,
- Input,
- FeatureType <: BaseFeatureStoreV1Feature[Query, Input, _ <: EntityId, _]
- ](
- features: Set[FeatureType]
- ): Map[DatasetId, Set[FeatureType]] = {
- val datasetsAndFeatures: Set[(DatasetId, FeatureType)] = features
- .flatMap { feature: FeatureType =>
- feature.boundFeatureSet.sourceDatasets.map(_.id).map { datasetId: DatasetId =>
- datasetId -> feature
- }
- }
-
- datasetsAndFeatures
- .groupBy { case (datasetId, _) => datasetId }.mapValues(_.map {
- case (_, feature) => feature
- })
- }
-
- /**
- * This takes a mapping of Feature Store Dataset => ProMix Features, as well as the dataset errors
- * from PredictionRecord and computing a final, deduped mapping from ProMix Feature to Exceptions.
- */
- def featureToHydrationErrors[
- Query <: PipelineQuery,
- Input,
- FeatureType <: BaseFeatureStoreV1Feature[Query, Input, _ <: EntityId, _]
- ](
- datasetToFeatures: Map[DatasetId, Set[
- FeatureType
- ]],
- errorsByDatasetId: DatasetErrorsById
- ): Map[FeatureType, Set[HydrationError]] = {
- val hasError = errorsByDatasetId.datasets.nonEmpty
- if (hasError) {
- val featuresAndErrors: Set[(FeatureType, Set[HydrationError])] = errorsByDatasetId.datasets
- .flatMap { id: DatasetId =>
- val errors: Set[HydrationError] = errorsByDatasetId.get(id).values.toSet
- if (errors.nonEmpty) {
- val datasetFeatures: Set[FeatureType] = datasetToFeatures.getOrElse(id, Set.empty)
- datasetFeatures.map { feature =>
- feature -> errors
- }.toSeq
- } else {
- Seq.empty
- }
- }
- featuresAndErrors
- .groupBy { case (feature, _) => feature }.mapValues(_.flatMap {
- case (_, errors: Set[HydrationError]) => errors
- })
- } else {
- Map.empty
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala
deleted file mode 100644
index e80d55302..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1
-
-import com.twitter.ml.api.util.SRichDataRecord
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.data.PredictionRecordAdapter
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.online.FeatureStoreRequest
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateEntity
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import com.twitter.util.logging.Logging
-
-trait FeatureStoreV1CandidateFeatureHydrator[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]]
- extends BaseBulkCandidateFeatureHydrator[
- Query,
- Candidate,
- BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _]
- ]
- with Logging {
-
- override def features: Set[BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _]]
-
- def clientBuilder: FeatureStoreV1DynamicClientBuilder
-
- private lazy val hydrationConfig = FeatureStoreV1CandidateFeatureHydrationConfig(features)
-
- private lazy val client = clientBuilder.build(hydrationConfig)
-
- private lazy val datasetToFeatures =
- FeatureStoreDatasetErrorHandler.datasetToFeaturesMapping(features)
-
- private lazy val dataRecordAdapter =
- PredictionRecordAdapter.oneToOne(hydrationConfig.allBoundFeatures)
-
- private lazy val featureContext = hydrationConfig.allBoundFeatures.toFeatureContext
-
- override def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]] = {
- // Duplicate entities are expected across features, so de-dupe via the Set before converting to Seq
- val entities: Seq[FeatureStoreV1CandidateEntity[Query, Candidate, _ <: EntityId]] =
- features.map(_.entity).toSeq
-
- val featureStoreRequests = candidates.map { candidate =>
- val candidateEntityIds: Seq[EntityWithId[_ <: EntityId]] =
- entities.map(_.entityWithId(query, candidate.candidate, candidate.features))
-
- FeatureStoreRequest(entityIds = candidateEntityIds)
- }
-
- val featureMaps = client(featureStoreRequests, query).map { predictionRecords =>
- if (predictionRecords.size == candidates.size)
- predictionRecords
- .zip(candidates).map {
- case (predictionRecord, candidate) =>
- val datasetErrors = predictionRecord.getDatasetHydrationErrors
- val errorMap =
- FeatureStoreDatasetErrorHandler.featureToHydrationErrors(
- datasetToFeatures,
- datasetErrors)
-
- if (errorMap.nonEmpty) {
- logger.debug(() =>
- s"$identifier hydration errors for candidate ${candidate.candidate.id}: $errorMap")
- }
- val dataRecord =
- new SRichDataRecord(
- dataRecordAdapter.adaptToDataRecord(predictionRecord),
- featureContext)
- val featureStoreResponse =
- FeatureStoreV1Response(dataRecord, errorMap)
- FeatureMapBuilder()
- .add(FeatureStoreV1ResponseFeature, featureStoreResponse).build()
- }
- else
- // Should not happen as FSv1 is guaranteed to return a prediction record per feature store request
- throw PipelineFailure(
- FeatureHydrationFailed,
- "Unexpected response length from Feature Store V1 while hydrating candidate features")
- }
-
- Stitch.callFuture(featureMaps)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala
deleted file mode 100644
index 70bcc15cf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1
-
-import com.twitter.ml.featurestore.lib.dynamic.BaseDynamicHydrationConfig
-import com.twitter.ml.featurestore.lib.dynamic.BaseGatedFeatures
-import com.twitter.ml.featurestore.lib.dynamic.DynamicFeatureStoreClient
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait FeatureStoreV1DynamicClientBuilder {
- def build[Query <: PipelineQuery](
- dynamicHydrationConfig: BaseDynamicHydrationConfig[Query, _ <: BaseGatedFeatures[Query]]
- ): DynamicFeatureStoreClient[Query]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala
deleted file mode 100644
index e740628fd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1
-
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.dynamic.BaseDynamicHydrationConfig
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-case class FeatureStoreV1QueryFeatureHydrationConfig[Query <: PipelineQuery](
- features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]])
- extends BaseDynamicHydrationConfig[
- Query,
- BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]
- ](features)
-
-case class FeatureStoreV1CandidateFeatureHydrationConfig[
- Query <: PipelineQuery,
- Input <: UniversalNoun[Any]
-](
- features: Set[BaseFeatureStoreV1CandidateFeature[Query, Input, _ <: EntityId, _]])
- extends BaseDynamicHydrationConfig[
- Query,
- BaseFeatureStoreV1CandidateFeature[Query, Input, _ <: EntityId, _]
- ](features)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala
deleted file mode 100644
index 143801e6f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1
-
-import com.twitter.ml.api.util.SRichDataRecord
-import com.twitter.ml.featurestore.lib.EntityId
-import com.twitter.ml.featurestore.lib.data.PredictionRecordAdapter
-import com.twitter.ml.featurestore.lib.entity.EntityWithId
-import com.twitter.ml.featurestore.lib.online.FeatureStoreRequest
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature
-import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryEntity
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-import com.twitter.util.logging.Logging
-
-trait FeatureStoreV1QueryFeatureHydrator[Query <: PipelineQuery]
- extends BaseQueryFeatureHydrator[
- Query,
- BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]
- ]
- with Logging {
-
- def features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]]
-
- def clientBuilder: FeatureStoreV1DynamicClientBuilder
-
- private lazy val hydrationConfig = FeatureStoreV1QueryFeatureHydrationConfig(features)
-
- private lazy val client = clientBuilder.build(hydrationConfig)
-
- private lazy val datasetToFeatures =
- FeatureStoreDatasetErrorHandler.datasetToFeaturesMapping(features)
-
- private lazy val dataRecordAdapter =
- PredictionRecordAdapter.oneToOne(hydrationConfig.allBoundFeatures)
-
- private lazy val featureContext = hydrationConfig.allBoundFeatures.toFeatureContext
-
- override def hydrate(
- query: Query
- ): Stitch[FeatureMap] = {
- // Duplicate entities are expected across features, so de-dupe via the Set before converting to Seq
- val entities: Seq[FeatureStoreV1QueryEntity[Query, _ <: EntityId]] =
- features.map(_.entity).toSeq
- val entityIds: Seq[EntityWithId[_ <: EntityId]] = entities.map(_.entityWithId(query))
-
- val featureStoreRequest = Seq(FeatureStoreRequest(entityIds = entityIds))
-
- val featureMap = client(featureStoreRequest, query).map { predictionRecords =>
- // Should not happen as FSv1 is guaranteed to return a prediction record per feature store request
- val predictionRecord = predictionRecords.headOption.getOrElse {
- throw PipelineFailure(
- FeatureHydrationFailed,
- "Unexpected empty response from Feature Store V1 while hydrating query features")
- }
-
- val datasetErrors = predictionRecord.getDatasetHydrationErrors
- val errorMap =
- FeatureStoreDatasetErrorHandler.featureToHydrationErrors(datasetToFeatures, datasetErrors)
-
- if (errorMap.nonEmpty) {
- logger.debug(() => s"$identifier hydration errors for query: $errorMap")
- }
-
- val richDataRecord =
- SRichDataRecord(dataRecordAdapter.adaptToDataRecord(predictionRecord), featureContext)
- val featureStoreResponse =
- FeatureStoreV1Response(richDataRecord, errorMap)
- FeatureMapBuilder().add(FeatureStoreV1ResponseFeature, featureStoreResponse).build()
- }
-
- Stitch.callFuture(featureMap)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD
deleted file mode 100644
index e3e7cf018..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala
deleted file mode 100644
index 7cf225838..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter.SupportsConditionally
-import com.twitter.product_mixer.core.model.common
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/**
- * Takes a sequence of candidates and can filter some out
- *
- * @note if you want to conditionally run a [[Filter]] you can use the mixin [[Filter.Conditionally]]
- * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use [[com.twitter.product_mixer.component_library.filter.ParamGatedFilter]]
- *
- * @tparam Query The domain model for the query or request
- * @tparam Candidate The type of the candidates
- */
-trait Filter[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends Component
- with SupportsConditionally[Query, Candidate] {
-
- /** @see [[FilterIdentifier]] */
- override val identifier: FilterIdentifier
-
- /**
- * Filter the list of candidates
- *
- * @return a FilterResult including both the list of kept candidate and the list of removed candidates
- */
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[FilterResult[Candidate]]
-}
-
-object Filter {
-
- /**
- * Mixin for when you want to conditionally run a [[Filter]]
- *
- * This is a thin wrapper around [[common.Conditionally]] exposing a nicer API for the [[Filter]] specific use-case.
- */
- trait Conditionally[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends common.Conditionally[Input[Query, Candidate]] { _: Filter[Query, Candidate] =>
-
- /** @see [[common.Conditionally.onlyIf]] */
- def onlyIf(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Boolean
-
- override final def onlyIf(input: Input[Query, Candidate]): Boolean =
- onlyIf(input.query, input.candidates)
- }
-
- /** Type alias to obscure [[Filter.Input]] from customers */
- type SupportsConditionally[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] =
- common.SupportsConditionally[Input[Query, Candidate]]
-
- /** A case class representing the input arguments to a [[Filter]], mostly for internal use */
- case class Input[+Query <: PipelineQuery, +Candidate <: UniversalNoun[Any]](
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala
deleted file mode 100644
index 436127381..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.filter
-
-/** `Candidate`s were `kept` and `removed` by a [[Filter]] */
-case class FilterResult[+Candidate](kept: Seq[Candidate], removed: Seq[Candidate])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD
deleted file mode 100644
index 73d60be75..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala
deleted file mode 100644
index 691f30c19..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate.SkippedResult
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-
-/**
- * A gate controls if a pipeline or other component is executed
- *
- * A gate is mostly controlled by it's `shouldContinue` function - when this function
- * returns true, execution Continues.
- *
- * Gates also have a optional `shouldSkip`- When it returns
- * true, then we Continue without executing `main`.
- *
- * @tparam Query The query type that the gate will receive as input
- *
- * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more
- * information.
- */
-
-sealed trait BaseGate[-Query <: PipelineQuery] extends Component {
- override val identifier: GateIdentifier
-
- /**
- * If a shouldSkip returns true, the gate returns a Skip(continue=true) without executing
- * the main predicate. We expect this to be useful for debugging, dogfooding, etc.
- */
- def shouldSkip(query: Query): Stitch[Boolean] = Stitch.False
-
- /**
- * The main predicate that controls this gate. If this predicate returns true, the gate returns Continue.
- */
- def shouldContinue(query: Query): Stitch[Boolean]
-
- /** returns a [[GateResult]] to determine whether a pipeline should be executed based on `t` */
- final def apply(t: Query): Stitch[GateResult] = {
- shouldSkip(t).flatMap { skipResult =>
- if (skipResult) {
- SkippedResult
- } else {
- shouldContinue(t).map { mainResult =>
- if (mainResult) GateResult.Continue else GateResult.Stop
- }
- }
- }
- }
-
- /** Arrow representation of `this` [[Gate]] */
- final def arrow: Arrow[Query, GateResult] = Arrow(apply)
-}
-
-/**
- * A regular Gate which only has access to the Query typed PipelineQuery. This can be used anywhere
- * Gates are available.
- *
- * A gate is mostly controlled by it's `shouldContinue` function - when this function
- * returns true, execution Continues.
- *
- * Gates also have a optional `shouldSkip`- When it returns
- * true, then we Continue without executing `main`.
- * @tparam Query The query type that the gate will receive as input
- *
- * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more
- * information.
- */
-trait Gate[-Query <: PipelineQuery] extends BaseGate[Query]
-
-/**
- * A Query And Candidate Gate which only has access both to the Query typed PipelineQuery and the
- * list of previously fetched candidates. This can be used on dependent candidate pipelines to
- * make a decision on whether to enable/disable them based on previous candidates.
- *
- * A gate is mostly controlled by it's `shouldContinue` function - when this function
- * returns true, execution Continues.
- *
- * Gates also have a optional `shouldSkip`- When it returns
- * true, then we Continue without executing `main`.
- *
- * @tparam Query The query type that the gate will receive as input
- *
- * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more
- * information.
- */
-trait QueryAndCandidateGate[-Query <: PipelineQuery] extends BaseGate[Query] {
-
- /**
- * If a shouldSkip returns true, the gate returns a Skip(continue=true) without executing
- * the main predicate. We expect this to be useful for debugging, dogfooding, etc.
- */
- def shouldSkip(query: Query, candidates: Seq[CandidateWithDetails]): Stitch[Boolean] =
- Stitch.False
-
- /**
- * The main predicate that controls this gate. If this predicate returns true, the gate returns Continue.
- */
- def shouldContinue(query: Query, candidates: Seq[CandidateWithDetails]): Stitch[Boolean]
-
- final override def shouldSkip(query: Query): Stitch[Boolean] = {
- val candidates = query.features
- .map(_.get(CandidatePipelineResults)).getOrElse(
- throw PipelineFailure(
- IllegalStateFailure,
- "Candidate Pipeline Results Feature missing from query features"))
- shouldSkip(query, candidates)
- }
-
- final override def shouldContinue(query: Query): Stitch[Boolean] = {
- val candidates = query.features
- .map(_.get(CandidatePipelineResults)).getOrElse(
- throw PipelineFailure(
- IllegalStateFailure,
- "Candidate Pipeline Results Feature missing from query features"))
- shouldContinue(query, candidates)
- }
-}
-
-object Gate {
- val SkippedResult: Stitch[GateResult] = Stitch.value(GateResult.Skipped)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala
deleted file mode 100644
index 8d7b9165c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.gate
-
-/**
- * A [[Gate]] controls if a pipeline or other component is executed.
- *
- * Application logic should usually use `GateResult.continue: Boolean` to interpret a GateResult. `continue` will be
- * true if we should continue with execution, and false if we should stop.
- *
- * You can case match against the `GateResult` to understand how exactly execution happened. See `object GateResult`
- * below, but this is useful if you want to know if we are continuing due to the skip or main predicates.
- */
-sealed trait GateResult {
-
- /** Should we continue? */
- val continue: Boolean
-}
-
-object GateResult {
-
- /**
- * Continue Execution
- *
- * the Skip predicate evaluated to true,
- * so we Skipped execution of the Main predicate and should continue
- */
- case object Skipped extends GateResult {
- override val continue = true
- }
-
- /**
- * Continue Execution
- *
- * the main predicate evaluated to true
- */
- case object Continue extends GateResult {
- override val continue = true
- }
-
- /**
- * Stop execution
- *
- * the main predicate evaluated to false
- */
- case object Stop extends GateResult {
- override val continue = false
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala
deleted file mode 100644
index c5a09d88c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.gate
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait ShouldContinue[Query <: PipelineQuery] {
- def apply(query: Query): Boolean
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD
deleted file mode 100644
index 8590c0c97..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala
deleted file mode 100644
index 0617d5733..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-
-object TransportMarshaller {
-
- /** Avoid `malformed class name` exceptions due to the presence of the `$` character */
- def getSimpleName[T](c: Class[T]): String = {
- c.getName.lastIndexOf("$") match {
- case -1 => c.getSimpleName
- case index => c.getName.substring(index + 1)
- }
- }
-}
-
-/**
- * Marshals a [[MarshallerInput]] into a type that can be sent over the wire
- *
- * This transformation should be mechanical and not contain business logic
- *
- * @note this is different from `com.twitter.product_mixer.core.functional_component.premarshaller`
- * which can contain business logic.
- */
-trait TransportMarshaller[-MarshallerInput <: HasMarshalling, +MarshallerOutput] extends Component {
-
- override val identifier: TransportMarshallerIdentifier
-
- def apply(input: MarshallerInput): MarshallerOutput
-}
-
-/**
- * No op marshalling that passes through a [[HasMarshalling]] into any type. This is useful if
- * the response does not need to be sent over the wire, such as with a
- * [[com.twitter.product_mixer.core.functional_component.candidate_source.product_pipeline.ProductPipelineCandidateSource]]
- */
-object NoOpTransportMarshaller extends TransportMarshaller[HasMarshalling, Any] {
- override val identifier: TransportMarshallerIdentifier = TransportMarshallerIdentifier("NoOp")
-
- override def apply(input: HasMarshalling): Any = input
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD
deleted file mode 100644
index 7ebb59e7f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala
deleted file mode 100644
index 6e3b91046..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.request
-
-import com.twitter.product_mixer.core.model.marshalling.request.ClientContext
-import com.twitter.product_mixer.core.{thriftscala => t}
-
-object ClientContextMarshaller {
-
- def apply(clientContext: ClientContext): t.ClientContext = {
- t.ClientContext(
- userId = clientContext.userId,
- guestId = clientContext.guestId,
- appId = clientContext.appId,
- ipAddress = clientContext.ipAddress,
- userAgent = clientContext.userAgent,
- countryCode = clientContext.countryCode,
- languageCode = clientContext.languageCode,
- isTwoffice = clientContext.isTwoffice,
- userRoles = clientContext.userRoles,
- deviceId = clientContext.deviceId,
- mobileDeviceId = clientContext.mobileDeviceId,
- mobileDeviceAdId = clientContext.mobileDeviceAdId,
- limitAdTracking = clientContext.limitAdTracking,
- guestIdAds = clientContext.guestIdAds,
- guestIdMarketing = clientContext.guestIdMarketing
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala
deleted file mode 100644
index 4bc48485a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.request
-
-import com.twitter.product_mixer.core.model.marshalling.request.ClientContext
-import com.twitter.product_mixer.core.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ClientContextUnmarshaller @Inject() () {
-
- def apply(clientContext: t.ClientContext): ClientContext = {
- ClientContext(
- userId = clientContext.userId,
- guestId = clientContext.guestId,
- guestIdAds = clientContext.guestIdAds,
- guestIdMarketing = clientContext.guestIdMarketing,
- appId = clientContext.appId,
- ipAddress = clientContext.ipAddress,
- userAgent = clientContext.userAgent,
- countryCode = clientContext.countryCode,
- languageCode = clientContext.languageCode,
- isTwoffice = clientContext.isTwoffice,
- userRoles = clientContext.userRoles.map(_.toSet),
- deviceId = clientContext.deviceId,
- mobileDeviceId = clientContext.mobileDeviceId,
- mobileDeviceAdId = clientContext.mobileDeviceAdId,
- limitAdTracking = clientContext.limitAdTracking
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala
deleted file mode 100644
index b693e2060..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.request
-
-import com.twitter.product_mixer.core.{thriftscala => t}
-import com.twitter.timelines.configapi.BooleanFeatureValue
-import com.twitter.timelines.configapi.FeatureValue
-import com.twitter.timelines.configapi.NumberFeatureValue
-import com.twitter.timelines.configapi.StringFeatureValue
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FeatureValueUnmarshaller @Inject() () {
-
- def apply(featureValue: t.FeatureValue): FeatureValue = featureValue match {
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.BoolValue(bool)) =>
- BooleanFeatureValue(bool)
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.StrValue(string)) =>
- StringFeatureValue(string)
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.IntValue(int)) =>
- NumberFeatureValue(int)
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.LongValue(long)) =>
- NumberFeatureValue(long)
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.DoubleValue(double)) =>
- NumberFeatureValue(double)
- case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.UnknownUnionField(field)) =>
- throw new UnsupportedOperationException(
- s"Unknown feature value primitive: ${field.field.name}")
- case t.FeatureValue.UnknownUnionField(field) =>
- throw new UnsupportedOperationException(s"Unknown feature value: ${field.field.name}")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD
deleted file mode 100644
index f340ee389..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala
deleted file mode 100644
index e65247485..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef
-import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ContextualTweetRefMarshaller @Inject() (
- tweetHydrationContextMarshaller: TweetHydrationContextMarshaller) {
-
- def apply(contextualTweetRef: ContextualTweetRef): thrift.ContextualTweetRef =
- thrift.ContextualTweetRef(
- id = contextualTweetRef.id,
- hydrationContext =
- contextualTweetRef.hydrationContext.map(tweetHydrationContextMarshaller(_)))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala
deleted file mode 100644
index 35ba7bfa3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.OuterTweetContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.QuoteTweetId
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.RetweetId
-import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class OuterTweetContextMarshaller @Inject() () {
-
- def apply(outerTweetContext: OuterTweetContext): thrift.OuterTweetContext =
- outerTweetContext match {
- case QuoteTweetId(id) => thrift.OuterTweetContext.QuoteTweetId(id)
- case RetweetId(id) => thrift.OuterTweetContext.RetweetId(id)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala
deleted file mode 100644
index a2bd6d82c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level.SafetyLevelMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.TweetHydrationContext
-import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetHydrationContextMarshaller @Inject() (
- safetyLevelMarshaller: SafetyLevelMarshaller,
- outerTweetContextMarshaller: OuterTweetContextMarshaller) {
-
- def apply(tweetHydrationContext: TweetHydrationContext): thrift.TweetHydrationContext =
- thrift.TweetHydrationContext(
- safetyLevelOverride = tweetHydrationContext.safetyLevelOverride.map(safetyLevelMarshaller(_)),
- outerTweetContext =
- tweetHydrationContext.outerTweetContext.map(outerTweetContextMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD
deleted file mode 100644
index afdc7e043..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala
deleted file mode 100644
index c2283082a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level
-
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationFocalTweetSafetyLevel
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationInjectedTweetSafetyLevel
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationReplySafetyLevel
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.SafetyLevel
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.TimelineFocalTweetSafetyLevel
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.TimelineHomePromotedHydrationSafetyLevel
-import com.twitter.spam.rtf.{thriftscala => thrift}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SafetyLevelMarshaller @Inject() () {
-
- def apply(safetyLevel: SafetyLevel): thrift.SafetyLevel = safetyLevel match {
- case ConversationFocalTweetSafetyLevel => thrift.SafetyLevel.ConversationFocalTweet
- case ConversationReplySafetyLevel => thrift.SafetyLevel.ConversationReply
- case ConversationInjectedTweetSafetyLevel => thrift.SafetyLevel.ConversationInjectedTweet
- case TimelineFocalTweetSafetyLevel => thrift.SafetyLevel.TimelineFocalTweet
- case TimelineHomePromotedHydrationSafetyLevel =>
- thrift.SafetyLevel.TimelineHomePromotedHydration
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD
deleted file mode 100644
index 98699bf17..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- "strato/config/src/thrift/com/twitter/strato/graphql:api-media-graphql-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql:topics-graphql-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala
deleted file mode 100644
index 50351870f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.slice
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.product_mixer.component_library.{thriftscala => t}
-import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor
-import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType
-import com.twitter.product_mixer.core.model.marshalling.response.slice.GapCursor
-
-@Singleton
-class CursorTypeMarshaller @Inject() () {
-
- def apply(cursorType: CursorType): t.CursorType = cursorType match {
- case NextCursor => t.CursorType.Next
- case PreviousCursor => t.CursorType.Previous
- case GapCursor => t.CursorType.Gap
- }
-
- def unmarshall(cursorType: t.CursorType): CursorType = cursorType match {
- case t.CursorType.Next => NextCursor
- case t.CursorType.Previous => PreviousCursor
- case t.CursorType.Gap => GapCursor
- case t.CursorType.EnumUnknownCursorType(id) =>
- throw new UnsupportedOperationException(
- s"Attempted to unmarshall unrecognized cursor type: $id")
- }
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala
deleted file mode 100644
index e3b1561c1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.slice
-
-import com.twitter.product_mixer.core.model.marshalling.response.slice.AdType
-import com.twitter.product_mixer.core.model.marshalling.response.slice
-import com.twitter.strato.graphql.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SliceItemMarshaller @Inject() () {
- def apply(item: slice.SliceItem): t.SliceItem = {
- item match {
- case item: slice.TweetItem =>
- t.SliceItem.TweetItem(t.TweetItem(id = item.id))
- case item: slice.UserItem =>
- t.SliceItem.UserItem(t.UserItem(id = item.id))
- case item: slice.TwitterListItem =>
- t.SliceItem.TwitterListItem(t.TwitterListItem(id = item.id))
- case item: slice.DMConvoSearchItem =>
- t.SliceItem.DmConvoSearchItem(t.DMConvoSearchItem(id = item.id))
- case item: slice.DMConvoItem =>
- t.SliceItem.DmConvoItem(t.DMConvoItem(id = item.id))
- case item: slice.DMEventItem =>
- t.SliceItem.DmEventItem(t.DMEventItem(id = item.id))
- case item: slice.DMMessageSearchItem =>
- t.SliceItem.DmMessageSearchItem(t.DMMessageSearchItem(id = item.id))
- case item: slice.TopicItem =>
- t.SliceItem.TopicItem(t.TopicItem(id = item.id.toString))
- case item: slice.TypeaheadEventItem =>
- t.SliceItem.TypeaheadEventItem(
- t.TypeaheadEventItem(
- eventId = item.eventId,
- metadata = item.metadata.map(marshalTypeaheadMetadata)
- )
- )
- case item: slice.TypeaheadQuerySuggestionItem =>
- t.SliceItem.TypeaheadQuerySuggestionItem(
- t.TypeaheadQuerySuggestionItem(
- query = item.query,
- metadata = item.metadata.map(marshalTypeaheadMetadata)
- )
- )
- case item: slice.TypeaheadUserItem =>
- t.SliceItem.TypeaheadUserItem(
- t.TypeaheadUserItem(
- userId = item.userId,
- metadata = item.metadata.map(marshalTypeaheadMetadata),
- badges = Some(item.badges.map { badge =>
- t.UserBadge(
- badgeUrl = badge.badgeUrl,
- description = Some(badge.description),
- badgeType = Some(badge.badgeType))
- })
- )
- )
- case item: slice.AdItem =>
- t.SliceItem.AdItem(
- t.AdItem(
- adKey = t.AdKey(
- adAccountId = item.adAccountId,
- adUnitId = item.adUnitId,
- )
- )
- )
- case item: slice.AdCreativeItem =>
- t.SliceItem.AdCreativeItem(
- t.AdCreativeItem(
- adCreativeKey = t.AdCreativeKey(
- adAccountId = item.adAccountId,
- adType = marshalAdType(item.adType),
- creativeId = item.creativeId
- )
- )
- )
- case item: slice.AdGroupItem =>
- t.SliceItem.AdGroupItem(
- t.AdGroupItem(
- adGroupKey = t.AdGroupKey(
- adAccountId = item.adAccountId,
- adGroupId = item.adGroupId
- )
- )
- )
- case item: slice.CampaignItem =>
- t.SliceItem.CampaignItem(
- t.CampaignItem(
- campaignKey = t.CampaignKey(
- adAccountId = item.adAccountId,
- campaignId = item.campaignId
- )
- )
- )
- case item: slice.FundingSourceItem =>
- t.SliceItem.FundingSourceItem(
- t.FundingSourceItem(
- fundingSourceKey = t.FundingSourceKey(
- adAccountId = item.adAccountId,
- fundingSourceId = item.fundingSourceId
- )
- )
- )
- }
- }
-
- private def marshalTypeaheadMetadata(metadata: slice.TypeaheadMetadata) = {
- t.TypeaheadMetadata(
- score = metadata.score,
- source = metadata.source,
- resultContext = metadata.context.map(context =>
- t.TypeaheadResultContext(
- displayString = context.displayString,
- contextType = marshalRequestContextType(context.contextType),
- iconUrl = context.iconUrl
- ))
- )
- }
-
- private def marshalRequestContextType(
- context: slice.TypeaheadResultContextType
- ): t.TypeaheadResultContextType = {
- context match {
- case slice.You => t.TypeaheadResultContextType.You
- case slice.Location => t.TypeaheadResultContextType.Location
- case slice.NumFollowers => t.TypeaheadResultContextType.NumFollowers
- case slice.FollowRelationship => t.TypeaheadResultContextType.FollowRelationship
- case slice.Bio => t.TypeaheadResultContextType.Bio
- case slice.NumTweets => t.TypeaheadResultContextType.NumTweets
- case slice.Trending => t.TypeaheadResultContextType.Trending
- case slice.HighlightedLabel => t.TypeaheadResultContextType.HighlightedLabel
- case _ => t.TypeaheadResultContextType.Undefined
- }
- }
-
- private def marshalAdType(
- adType: AdType
- ): t.AdType = {
- adType match {
- case AdType.Tweet => t.AdType.Tweet
- case AdType.Account => t.AdType.Account
- case AdType.InStreamVideo => t.AdType.InStreamVideo
- case AdType.DisplayCreative => t.AdType.DisplayCreative
- case AdType.Trend => t.AdType.Trend
- case AdType.Spotlight => t.AdType.Spotlight
- case AdType.Takeover => t.AdType.Takeover
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala
deleted file mode 100644
index a59102940..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.slice
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.slice.Slice
-import com.twitter.strato.graphql.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SliceTransportMarshaller @Inject() (sliceItemMarshaller: SliceItemMarshaller)
- extends TransportMarshaller[Slice, t.SliceResult] {
-
- override val identifier: TransportMarshallerIdentifier = TransportMarshallerIdentifier("Slice")
-
- override def apply(slice: Slice): t.SliceResult = {
- t.SliceResult.Slice(
- t.Slice(
- items = slice.items.map(sliceItemMarshaller(_)),
- sliceInfo = t.SliceInfo(
- previousCursor = slice.sliceInfo.previousCursor,
- nextCursor = slice.sliceInfo.nextCursor
- )
- ))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD
deleted file mode 100644
index 214dfdda1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- "src/thrift/com/twitter/pages/render:thrift-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/timelines:graphql-timelines-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- "src/thrift/com/twitter/pages/render:thrift-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/timelines:graphql-timelines-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala
deleted file mode 100644
index ecd8386b0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody
-import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimelinesPageBody
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TimelineKeyPageBody
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PageBodyMarshaller @Inject() (
- timelineKeyMarshaller: TimelineKeyMarshaller,
- segmentedTimelinesMarshaller: SegmentedTimelinesMarshaller) {
-
- def apply(pageBody: PageBody): urp.PageBody = pageBody match {
- case pageBody: TimelineKeyPageBody =>
- urp.PageBody.Timeline(timelineKeyMarshaller(pageBody.timeline))
- case pageBody: SegmentedTimelinesPageBody =>
- urp.PageBody.SegmentedTimelines(segmentedTimelinesMarshaller(pageBody))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala
deleted file mode 100644
index 656c1f165..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeader
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PageHeaderMarshaller @Inject() (
- topicPageHeaderMarshaller: TopicPageHeaderMarshaller) {
-
- def apply(pageHeader: PageHeader): urp.PageHeader = pageHeader match {
- case pageHeader: TopicPageHeader =>
- urp.PageHeader.TopicPageHeader(topicPageHeaderMarshaller(pageHeader))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala
deleted file mode 100644
index da03466bf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageNavBar
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TitleNavBar
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PageNavBarMarshaller @Inject() (
- topicPageNavBarMarshaller: TopicPageNavBarMarshaller,
- titleNavBarMarshaller: TitleNavBarMarshaller) {
-
- def apply(pageNavBar: PageNavBar): urp.PageNavBar = pageNavBar match {
- case pageNavBar: TopicPageNavBar =>
- urp.PageNavBar.TopicPageNavBar(topicPageNavBarMarshaller(pageNavBar))
- case pageNavBar: TitleNavBar =>
- urp.PageNavBar.TitleNavBar(titleNavBarMarshaller(pageNavBar))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala
deleted file mode 100644
index 1d2bdc504..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimeline
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SegmentedTimelineMarshaller @Inject() (
- timelineKeyMarshaller: TimelineKeyMarshaller,
- timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller) {
-
- def apply(segmentedTimeline: SegmentedTimeline): urp.SegmentedTimeline = urp.SegmentedTimeline(
- id = segmentedTimeline.id,
- labelText = segmentedTimeline.labelText,
- timeline = timelineKeyMarshaller(segmentedTimeline.timeline),
- scribeConfig = segmentedTimeline.scribeConfig.map(timelineScribeConfigMarshaller(_)),
- refreshIntervalSec = segmentedTimeline.refreshIntervalSec
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala
deleted file mode 100644
index a05e0037f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimelinesPageBody
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SegmentedTimelinesMarshaller @Inject() (
- segmentedTimelineMarshaller: SegmentedTimelineMarshaller) {
-
- def apply(segmentedTimelinesPageBody: SegmentedTimelinesPageBody): urp.SegmentedTimelines =
- urp.SegmentedTimelines(
- initialTimeline = segmentedTimelineMarshaller(segmentedTimelinesPageBody.initialTimeline),
- timelines = segmentedTimelinesPageBody.timelines.map(segmentedTimelineMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala
deleted file mode 100644
index 91936e4d0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urp.FollowedTopicsMeTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.FollowedTopicsOtherTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.ForYouExploreMixerTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NoteworthyAccountsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NotInterestedTopicsMeTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxForYouCategoryUserRecommendationsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxGeoCategoryUserRecommendationsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxPymkCategoryUserRecommendationsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxSingleInterestCategoryUserRecommendationsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxUserRecommendationsTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.ShoppingHomeTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TimelineKey
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicsLandingTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicsPickerTimeline
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TrendingExploreMixerTimeline
-import com.twitter.strato.graphql.timelines.{thriftscala => graphql}
-import javax.inject.Singleton
-
-@Singleton
-class TimelineKeyMarshaller {
-
- def apply(timelineKey: TimelineKey): graphql.TimelineKey = timelineKey match {
- case TopicsLandingTimeline(topicId) =>
- graphql.TimelineKey.TopicTimeline(graphql.TopicId(topicId))
- case NoteworthyAccountsTimeline(topicId) =>
- graphql.TimelineKey.NoteworthyAccountsTimeline(graphql.TopicId(topicId))
- case TopicsPickerTimeline(topicId) =>
- graphql.TimelineKey.TopicsPickerTimeline(graphql.TopicId(topicId))
- case FollowedTopicsMeTimeline() =>
- graphql.TimelineKey.FollowedTopicsMeTimeline(graphql.Void())
- case NotInterestedTopicsMeTimeline() =>
- graphql.TimelineKey.NotInterestedTopicsMeTimeline(graphql.Void())
- case FollowedTopicsOtherTimeline(userId) =>
- graphql.TimelineKey.FollowedTopicsOtherTimeline(userId)
- case NuxUserRecommendationsTimeline() =>
- graphql.TimelineKey.NuxUserRecommendationsTimeline(graphql.Void())
- case NuxForYouCategoryUserRecommendationsTimeline() =>
- graphql.TimelineKey.NuxForYouCategoryUserRecommendationsTimeline(graphql.Void())
- case NuxPymkCategoryUserRecommendationsTimeline() =>
- graphql.TimelineKey.NuxPymkCategoryUserRecommendationsTimeline(graphql.Void())
- case NuxGeoCategoryUserRecommendationsTimeline() =>
- graphql.TimelineKey.NuxGeoCategoryUserRecommendationsTimeline(graphql.Void())
- case NuxSingleInterestCategoryUserRecommendationsTimeline(topicId) =>
- graphql.TimelineKey.NuxSingleInterestCategoryUserRecommendationsTimeline(
- graphql.TopicId(topicId))
- case ShoppingHomeTimeline() => graphql.TimelineKey.ShoppingHome(graphql.Void())
- case ForYouExploreMixerTimeline() =>
- graphql.TimelineKey.ForYouExploreMixerTimeline(graphql.Void())
- case TrendingExploreMixerTimeline() =>
- graphql.TimelineKey.TrendingExploreMixerTimeline(graphql.Void())
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala
deleted file mode 100644
index 446771772..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TitleNavBar
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TitleNavBarMarshaller @Inject() (
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(titleNavBar: TitleNavBar): urp.TitleNavBar =
- urp.TitleNavBar(
- title = titleNavBar.title,
- subtitle = titleNavBar.subtitle,
- clientEventInfo = titleNavBar.clientEventInfo.map(clientEventInfoMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala
deleted file mode 100644
index 9644ee6d4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urp.BasicTopicPageHeaderDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urp.PersonalizedTopicPageHeaderDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeaderDisplayType
-import com.twitter.pages.render.{thriftscala => urp}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicPageHeaderDisplayTypeMarshaller @Inject() () {
-
- def apply(
- topicPageHeaderDisplayType: TopicPageHeaderDisplayType
- ): urp.TopicPageHeaderDisplayType = topicPageHeaderDisplayType match {
- case BasicTopicPageHeaderDisplayType => urp.TopicPageHeaderDisplayType.Basic
- case PersonalizedTopicPageHeaderDisplayType => urp.TopicPageHeaderDisplayType.Personalized
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala
deleted file mode 100644
index d15585bdd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeaderFacepile
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicPageHeaderFacepileMarshaller @Inject() (
- urlMarshaller: UrlMarshaller) {
-
- def apply(topicPageHeaderFacepile: TopicPageHeaderFacepile): urp.TopicPageHeaderFacepile =
- urp.TopicPageHeaderFacepile(
- userIds = topicPageHeaderFacepile.userIds,
- facepileUrl = topicPageHeaderFacepile.facepileUrl.map(urlMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala
deleted file mode 100644
index 44c4fa48a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeader
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicPageHeaderMarshaller @Inject() (
- topicPageHeaderFacepileMarshaller: TopicPageHeaderFacepileMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- topicPageHeaderDisplayTypeMarshaller: TopicPageHeaderDisplayTypeMarshaller) {
-
- def apply(topicPageHeader: TopicPageHeader): urp.TopicPageHeader =
- urp.TopicPageHeader(
- topicId = topicPageHeader.topicId,
- facepile = topicPageHeader.facepile.map(topicPageHeaderFacepileMarshaller(_)),
- clientEventInfo = topicPageHeader.clientEventInfo.map(clientEventInfoMarshaller(_)),
- landingContext = topicPageHeader.landingContext,
- displayType = topicPageHeader.displayType
- .map(topicPageHeaderDisplayTypeMarshaller(_)).getOrElse(
- urp.TopicPageHeaderDisplayType.Basic)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala
deleted file mode 100644
index 9bf0838e2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageNavBar
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicPageNavBarMarshaller @Inject() (
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(topicPageNavBar: TopicPageNavBar): urp.TopicPageNavBar =
- urp.TopicPageNavBar(
- topicId = topicPageNavBar.topicId,
- clientEventInfo = topicPageNavBar.clientEventInfo.map(clientEventInfoMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala
deleted file mode 100644
index 45f5dd721..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.urp.Page
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UrpTransportMarshaller @Inject() (
- pageBodyMarshaller: PageBodyMarshaller,
- timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller,
- pageHeaderMarshaller: PageHeaderMarshaller,
- pageNavBarMarshaller: PageNavBarMarshaller)
- extends TransportMarshaller[Page, urp.Page] {
-
- override val identifier: TransportMarshallerIdentifier =
- TransportMarshallerIdentifier("UnifiedRichPage")
-
- override def apply(page: Page): urp.Page = urp.Page(
- id = page.id,
- pageBody = pageBodyMarshaller(page.pageBody),
- scribeConfig = page.scribeConfig.map(timelineScribeConfigMarshaller(_)),
- pageHeader = page.pageHeader.map(pageHeaderMarshaller(_)),
- pageNavBar = page.pageNavBar.map(pageNavBarMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala
deleted file mode 100644
index c9f5f597d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urp
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ArticleDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CommerceDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ConversationDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ConversationSectionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.LiveEventDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.TimelinesDetailsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrtEndpointOptionsMarshaller
-
-object UrpTransportMarshallerBuilder {
- // Convenience constructor for services not using dependency injection and unit tests. If using
- // dependency injection, instead @Inject an instance of UrpTransportMarshaller to construct.
-
- val timelineKeyMarshaller = new TimelineKeyMarshaller
- val timelineScribeConfigMarshaller = new TimelineScribeConfigMarshaller
- val urlMarshaller = new UrlMarshaller(new UrlTypeMarshaller, new UrtEndpointOptionsMarshaller)
- val clientEventInfoMarshaller = new ClientEventInfoMarshaller(
- new ClientEventDetailsMarshaller(
- new ConversationDetailsMarshaller(new ConversationSectionMarshaller),
- new TimelinesDetailsMarshaller,
- new ArticleDetailsMarshaller,
- new LiveEventDetailsMarshaller,
- new CommerceDetailsMarshaller)
- )
-
- val segmentedTimelineMarshaller =
- new SegmentedTimelineMarshaller(timelineKeyMarshaller, timelineScribeConfigMarshaller)
- val segmentedTimelinesMarshaller = new SegmentedTimelinesMarshaller(segmentedTimelineMarshaller)
-
- val pageBodyMarshaller: PageBodyMarshaller = new PageBodyMarshaller(
- timelineKeyMarshaller,
- segmentedTimelinesMarshaller
- )
-
- val topicPageHeaderFacepileMarshaller = new TopicPageHeaderFacepileMarshaller(urlMarshaller)
- val topicPageHeaderDisplayTypeMarshaller = new TopicPageHeaderDisplayTypeMarshaller
- val topicPageHeaderMarshaller = new TopicPageHeaderMarshaller(
- topicPageHeaderFacepileMarshaller,
- clientEventInfoMarshaller,
- topicPageHeaderDisplayTypeMarshaller
- )
- val pageHeaderMarshaller: PageHeaderMarshaller = new PageHeaderMarshaller(
- topicPageHeaderMarshaller)
-
- val topicPageNavBarMarshaller = new TopicPageNavBarMarshaller(clientEventInfoMarshaller)
- val titleNavBarMarshaller = new TitleNavBarMarshaller(clientEventInfoMarshaller)
- val pageNavBarMarshaller: PageNavBarMarshaller = new PageNavBarMarshaller(
- topicPageNavBarMarshaller,
- titleNavBarMarshaller
- )
-
- val marshaller: UrpTransportMarshaller =
- new UrpTransportMarshaller(
- pageBodyMarshaller = pageBodyMarshaller,
- timelineScribeConfigMarshaller = timelineScribeConfigMarshaller,
- pageHeaderMarshaller = pageHeaderMarshaller,
- pageNavBarMarshaller = pageNavBarMarshaller
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala
deleted file mode 100644
index 6effca5ae..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AddEntriesInstructionMarshaller @Inject() (
- timelineEntryMarshaller: TimelineEntryMarshaller) {
-
- def apply(instruction: AddEntriesTimelineInstruction): urt.AddEntries = urt.AddEntries(
- entries = instruction.entries.map(timelineEntryMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala
deleted file mode 100644
index ce0c37139..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AddToModuleInstructionMarshaller @Inject() (moduleItemMarshaller: ModuleItemMarshaller) {
-
- def apply(instruction: AddToModuleTimelineInstruction): urt.AddToModule = urt.AddToModule(
- moduleItems = instruction.moduleItems.map(moduleItemMarshaller(_, instruction.moduleEntryId)),
- moduleEntryId = instruction.moduleEntryId,
- moduleItemEntryId = instruction.moduleItemEntryId,
- prepend = instruction.prepend
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD
deleted file mode 100644
index c2f8069b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "src/thrift/com/twitter/spam/rtf:safety-level-scala",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala
deleted file mode 100644
index d7bc4e8d4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CoverMarshaller @Inject() (
- coverContentMarshaller: CoverContentMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(cover: Cover): urt.ShowCover = cover match {
- case halfCover: HalfCover =>
- urt.ShowCover(
- cover = coverContentMarshaller(halfCover.content),
- clientEventInfo = cover.clientEventInfo.map(clientEventInfoMarshaller(_)))
- case fullCover: FullCover =>
- urt.ShowCover(
- cover = coverContentMarshaller(fullCover.content),
- clientEventInfo = cover.clientEventInfo.map(clientEventInfoMarshaller(_)))
- }
-}
-
-class UnsupportedTimelineCoverException(cover: Cover)
- extends UnsupportedOperationException(
- "Unsupported timeline cover " + TransportMarshaller.getSimpleName(cover.getClass))
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala
deleted file mode 100644
index 4f0e94c44..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class MarkEntriesUnreadInstructionMarshaller @Inject() () {
-
- def apply(instruction: MarkEntriesUnreadInstruction): urt.MarkEntriesUnread =
- urt.MarkEntriesUnread(entryIds = instruction.entryIds)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala
deleted file mode 100644
index 439ce87da..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleItemMarshaller @Inject() (
- timelineItemMarshaller: TimelineItemMarshaller,
- moduleItemTreeDisplayMarshaller: ModuleItemTreeDisplayMarshaller) {
-
- def apply(moduleItem: ModuleItem, moduleEntryId: String): urt.ModuleItem = urt.ModuleItem(
- /* Module items have an identifier comprising both the module entry id and the module item id.
- Some URT clients will deduplicate globally across different modules.
- Using the entry id as a prefix ensures that deduplication only happens within a single module,
- which we believe better aligns with engineers' intentions. */
- entryId = moduleEntryId + "-" + moduleItem.item.entryIdentifier,
- item = timelineItemMarshaller(moduleItem.item),
- dispensable = moduleItem.dispensable,
- treeDisplay = moduleItem.treeDisplay.map(moduleItemTreeDisplayMarshaller.apply)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala
deleted file mode 100644
index 26f93db2a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleDisplayTypeMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleItemTreeDisplayMarshaller @Inject() (
- moduleDisplayTypeMarshaller: ModuleDisplayTypeMarshaller) {
-
- def apply(moduleItemTreeDisplay: ModuleItemTreeDisplay): urt.ModuleItemTreeDisplay =
- urt.ModuleItemTreeDisplay(
- parentModuleItemEntryId = moduleItemTreeDisplay.parentModuleEntryItemId,
- indentFromParent = moduleItemTreeDisplay.indentFromParent,
- displayType = moduleItemTreeDisplay.displayType.map(moduleDisplayTypeMarshaller(_)),
- isAnchorChild = moduleItemTreeDisplay.isAnchorChild
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala
deleted file mode 100644
index 62eb202d9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PinEntryInstructionMarshaller @Inject() (
- timelineEntryMarshaller: TimelineEntryMarshaller) {
-
- def apply(instruction: PinEntryTimelineInstruction): urt.PinEntry = {
- urt.PinEntry(entry = timelineEntryMarshaller(instruction.entry))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala
deleted file mode 100644
index d0c71e3aa..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ReaderModeConfig
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReaderModeConfigMarshaller @Inject() (urlMarshaller: UrlMarshaller) {
-
- def apply(readerModeConfig: ReaderModeConfig): urt.ReaderModeConfig = urt.ReaderModeConfig(
- isReaderModeAvailable = readerModeConfig.isReaderModeAvailable,
- landingUrl = urlMarshaller(readerModeConfig.landingUrl)
- )
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala
deleted file mode 100644
index 5011721b8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReplaceEntryInstructionMarshaller @Inject() (
- timelineEntryMarshaller: TimelineEntryMarshaller) {
-
- def apply(instruction: ReplaceEntryTimelineInstruction): urt.ReplaceEntry = {
- val instructionEntry = instruction.entry
- urt.ReplaceEntry(
- entryIdToReplace = instructionEntry.entryIdToReplace
- .getOrElse(throw new MissingEntryToReplaceException(instructionEntry)),
- entry = timelineEntryMarshaller(instructionEntry)
- )
- }
-}
-
-class MissingEntryToReplaceException(entry: TimelineEntry)
- extends IllegalArgumentException(
- s"Missing entry ID to replace ${TransportMarshaller.getSimpleName(entry.getClass)}")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala
deleted file mode 100644
index 5a5eec0e7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertColorConfigurationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertDisplayLocationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconDisplayInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertNavigationMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ShowAlertInstructionMarshaller @Inject() (
- showAlertTypeMarshaller: ShowAlertTypeMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- richTextMarshaller: RichTextMarshaller,
- showAlertIconDisplayInfoMarshaller: ShowAlertIconDisplayInfoMarshaller,
- showAlertColorConfigurationMarshaller: ShowAlertColorConfigurationMarshaller,
- showAlertDisplayLocationMarshaller: ShowAlertDisplayLocationMarshaller,
- showAlertNavigationMetadataMarshaller: ShowAlertNavigationMetadataMarshaller,
-) {
-
- def apply(instruction: ShowAlertInstruction): urt.ShowAlert = urt.ShowAlert(
- alertType = showAlertTypeMarshaller(instruction.showAlert.alertType),
- triggerDelayMs = instruction.showAlert.triggerDelay.map(_.inMillis.toInt),
- displayDurationMs = instruction.showAlert.displayDuration.map(_.inMillis.toInt),
- clientEventInfo = instruction.showAlert.clientEventInfo.map(clientEventInfoMarshaller(_)),
- collapseDelayMs = instruction.showAlert.collapseDelay.map(_.inMillis.toInt),
- userIds = instruction.showAlert.userIds,
- richText = instruction.showAlert.richText.map(richTextMarshaller(_)),
- iconDisplayInfo =
- instruction.showAlert.iconDisplayInfo.map(showAlertIconDisplayInfoMarshaller(_)),
- colorConfig = showAlertColorConfigurationMarshaller(instruction.showAlert.colorConfig),
- displayLocation = showAlertDisplayLocationMarshaller(instruction.showAlert.displayLocation),
- navigationMetadata =
- instruction.showAlert.navigationMetadata.map(showAlertNavigationMetadataMarshaller(_)),
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala
deleted file mode 100644
index 5fa2a9bab..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.BottomTermination
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TopTermination
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TopAndBottomTermination
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TerminateTimelineInstructionMarshaller @Inject() () {
-
- def apply(instruction: TerminateTimelineInstruction): urt.TerminateTimeline =
- urt.TerminateTimeline(
- direction = instruction.terminateTimelineDirection match {
- case TopTermination => urt.TimelineTerminationDirection.Top
- case BottomTermination => urt.TimelineTerminationDirection.Bottom
- case TopAndBottomTermination => urt.TimelineTerminationDirection.TopAndBottom
- }
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala
deleted file mode 100644
index 2589df862..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineEntryContentMarshaller @Inject() (
- timelineItemMarshaller: TimelineItemMarshaller,
- timelineModuleMarshaller: TimelineModuleMarshaller,
- timelineOperationMarshaller: TimelineOperationMarshaller) {
-
- def apply(entry: TimelineEntry): urt.TimelineEntryContent = entry match {
- case item: TimelineItem =>
- urt.TimelineEntryContent.Item(timelineItemMarshaller(item))
- case module: TimelineModule =>
- urt.TimelineEntryContent.TimelineModule(timelineModuleMarshaller(module))
- case operation: TimelineOperation =>
- urt.TimelineEntryContent.Operation(timelineOperationMarshaller(operation))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala
deleted file mode 100644
index 8d937289c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineEntryMarshaller @Inject() (
- timelineEntryContentMarshaller: TimelineEntryContentMarshaller) {
-
- def apply(entry: TimelineEntry): urt.TimelineEntry =
- urt.TimelineEntry(
- entryId = entry.entryIdentifier,
- sortIndex = entry.sortIndex.getOrElse(throw new TimelineEntryMissingSortIndexException),
- content = timelineEntryContentMarshaller(entry),
- expiryTime = entry.expirationTimeInMillis
- )
-}
-
-class TimelineEntryMissingSortIndexException
- extends UnsupportedOperationException("Timeline entry missing sort index")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala
deleted file mode 100644
index e3727dab2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ClearCacheTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowCoverInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineInstructionMarshaller @Inject() (
- addEntriesInstructionMarshaller: AddEntriesInstructionMarshaller,
- addToModuleInstructionMarshaller: AddToModuleInstructionMarshaller,
- markEntriesUnreadInstructionMarshaller: MarkEntriesUnreadInstructionMarshaller,
- pinEntryInstructionMarshaller: PinEntryInstructionMarshaller,
- replaceEntryInstructionMarshaller: ReplaceEntryInstructionMarshaller,
- showAlertInstructionMarshaller: ShowAlertInstructionMarshaller,
- terminateTimelineInstructionMarshaller: TerminateTimelineInstructionMarshaller,
- coverMarshaller: CoverMarshaller) {
-
- def apply(instruction: TimelineInstruction): urt.TimelineInstruction = instruction match {
- case instruction: AddEntriesTimelineInstruction =>
- urt.TimelineInstruction.AddEntries(addEntriesInstructionMarshaller(instruction))
- case instruction: AddToModuleTimelineInstruction =>
- urt.TimelineInstruction.AddToModule(addToModuleInstructionMarshaller(instruction))
- case _: ClearCacheTimelineInstruction =>
- urt.TimelineInstruction.ClearCache(urt.ClearCache())
- case instruction: MarkEntriesUnreadInstruction =>
- urt.TimelineInstruction.MarkEntriesUnread(
- markEntriesUnreadInstructionMarshaller(instruction)
- )
- case instruction: PinEntryTimelineInstruction =>
- urt.TimelineInstruction.PinEntry(pinEntryInstructionMarshaller(instruction))
- case instruction: ReplaceEntryTimelineInstruction =>
- urt.TimelineInstruction.ReplaceEntry(replaceEntryInstructionMarshaller(instruction))
- case instruction: ShowCoverInstruction =>
- urt.TimelineInstruction.ShowCover(coverMarshaller(instruction.cover))
- case instruction: ShowAlertInstruction =>
- urt.TimelineInstruction.ShowAlert(showAlertInstructionMarshaller(instruction))
- case instruction: TerminateTimelineInstruction =>
- urt.TimelineInstruction.TerminateTimeline(terminateTimelineInstructionMarshaller(instruction))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala
deleted file mode 100644
index dee74d6b1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductGroupItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space.AudioSpaceItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label.IconLabelItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message.MessagePromptItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment.MomentAnnotationItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt.PromptItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend.TrendItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorItemMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label.LabelItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread.ThreadHeaderItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineItemContentMarshaller @Inject() (
- articleItemMarshaller: ArticleItemMarshaller,
- audioSpaceItemMarshaller: AudioSpaceItemMarshaller,
- cardItemMarshaller: CardItemMarshaller,
- cursorItemMarshaller: CursorItemMarshaller,
- eventSummaryItemMarshaller: EventSummaryItemMarshaller,
- iconLabelItemMarshaller: IconLabelItemMarshaller,
- labelItemMarshaller: LabelItemMarshaller,
- messagePromptItemMarshaller: MessagePromptItemMarshaller,
- tileItemMarshaller: TileItemMarshaller,
- tombstoneItemMarshaller: TombstoneItemMarshaller,
- topicFollowPromptItemMarshaller: TopicFollowPromptItemMarshaller,
- topicItemMarshaller: TopicItemMarshaller,
- tweetComposerItemMarshaller: TweetComposerItemMarshaller,
- tweetItemMarshaller: TweetItemMarshaller,
- twitterListItemMarshaller: TwitterListItemMarshaller,
- userItemMarshaller: UserItemMarshaller,
- verticalGridItemMarshaller: VerticalGridItemMarshaller,
- threadHeaderItemMarshaller: ThreadHeaderItemMarshaller,
- promptItemMarshaller: PromptItemMarshaller,
- spellingItemMarshaller: SpellingItemMarshaller,
- momentAnnotationItemMarshaller: MomentAnnotationItemMarshaller,
- genericSummaryItemMarshaller: GenericSummaryItemMarshaller,
- commerceProductItemMarshaller: CommerceProductItemMarshaller,
- commerceProductGroupItemMarshaller: CommerceProductGroupItemMarshaller,
- trendItemMarshaller: TrendItemMarshaller) {
-
- def apply(item: TimelineItem): urt.TimelineItemContent = item match {
- case articleItem: ArticleItem => articleItemMarshaller(articleItem)
- case audioSpaceItem: AudioSpaceItem => audioSpaceItemMarshaller(audioSpaceItem)
- case cardItem: CardItem => cardItemMarshaller(cardItem)
- case cursorItem: CursorItem => cursorItemMarshaller(cursorItem)
- case eventSummaryItem: EventSummaryItem => eventSummaryItemMarshaller(eventSummaryItem)
- case genericSummaryItem: GenericSummaryItem => genericSummaryItemMarshaller(genericSummaryItem)
- case iconLabelItem: IconLabelItem => iconLabelItemMarshaller(iconLabelItem)
- case labelItem: LabelItem => labelItemMarshaller(labelItem)
- case messagePromptItem: MessagePromptItem => messagePromptItemMarshaller(messagePromptItem)
- case tileItem: TileItem => tileItemMarshaller(tileItem)
- case tombstoneItem: TombstoneItem => tombstoneItemMarshaller(tombstoneItem)
- case topicFollowPromptItem: TopicFollowPromptItem =>
- topicFollowPromptItemMarshaller(topicFollowPromptItem)
- case topicItem: TopicItem => topicItemMarshaller(topicItem)
- case tweetComposerItem: TweetComposerItem => tweetComposerItemMarshaller(tweetComposerItem)
- case tweetItem: TweetItem => tweetItemMarshaller(tweetItem)
- case twitterListItem: TwitterListItem => twitterListItemMarshaller(twitterListItem)
- case userItem: UserItem => userItemMarshaller(userItem)
- case verticalGridItem: VerticalGridItem => verticalGridItemMarshaller(verticalGridItem)
- case threadHeaderItem: ThreadHeaderItem => threadHeaderItemMarshaller(threadHeaderItem)
- case promptItem: PromptItem => promptItemMarshaller(promptItem)
- case spellingItem: SpellingItem => spellingItemMarshaller(spellingItem)
- case momentAnnotationItem: MomentAnnotationItem =>
- momentAnnotationItemMarshaller(momentAnnotationItem)
- case commerceProductItem: CommerceProductItem =>
- commerceProductItemMarshaller(commerceProductItem)
- case commerceProductGroupItem: CommerceProductGroupItem =>
- commerceProductGroupItemMarshaller(commerceProductGroupItem)
- case trendItem: TrendItem => trendItemMarshaller(trendItem)
- case _: Cover => throw TimelineCoverNotFilteredException
- case _ => throw new UnsupportedTimelineItemException(item)
- }
-}
-
-class UnsupportedTimelineItemException(timelineItem: TimelineItem)
- extends UnsupportedOperationException(
- "Unsupported timeline item " + TransportMarshaller.getSimpleName(timelineItem.getClass))
-
-object TimelineCoverNotFilteredException
- extends UnsupportedOperationException("AddEntriesInstructionBuilder does not support Cover. " +
- "ShowCoverInstructionBuilder should be used with AddEntriesWithShowCoverInstructionBuilder " +
- "in order to filter out the Cover.")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala
deleted file mode 100644
index 242fdc522..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineItemMarshaller @Inject() (
- timelineItemContentMarshaller: TimelineItemContentMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- feedbackInfoMarshaller: FeedbackInfoMarshaller) {
-
- def apply(item: TimelineItem): urt.TimelineItem = urt.TimelineItem(
- content = timelineItemContentMarshaller(item),
- clientEventInfo = item.clientEventInfo.map(clientEventInfoMarshaller(_)),
- feedbackInfo = item.feedbackActionInfo.map(feedbackInfoMarshaller(_)),
- prompt = None
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala
deleted file mode 100644
index 792859941..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineMetadataMarshaller @Inject() (
- timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller,
- readerModeConfigMarshaller: ReaderModeConfigMarshaller) {
-
- def apply(timelineMetadata: TimelineMetadata): urt.TimelineMetadata = urt.TimelineMetadata(
- title = timelineMetadata.title,
- scribeConfig = timelineMetadata.scribeConfig.map(timelineScribeConfigMarshaller(_)),
- readerModeConfig = timelineMetadata.readerModeConfig.map(readerModeConfigMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala
deleted file mode 100644
index 4de8d6164..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleFooterMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleHeaderMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleShowMoreBehaviorMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineModuleMarshaller @Inject() (
- moduleItemMarshaller: ModuleItemMarshaller,
- moduleDisplayTypeMarshaller: ModuleDisplayTypeMarshaller,
- moduleHeaderMarshaller: ModuleHeaderMarshaller,
- moduleFooterMarshaller: ModuleFooterMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- feedbackInfoMarshaller: FeedbackInfoMarshaller,
- moduleMetadataMarshaller: ModuleMetadataMarshaller,
- moduleShowMoreBehaviorMarshaller: ModuleShowMoreBehaviorMarshaller) {
-
- def apply(timelineModule: TimelineModule): urt.TimelineModule = urt.TimelineModule(
- items = timelineModule.items.map(moduleItemMarshaller(_, timelineModule.entryIdentifier)),
- displayType = moduleDisplayTypeMarshaller(timelineModule.displayType),
- header = timelineModule.header.map(moduleHeaderMarshaller(_)),
- footer = timelineModule.footer.map(moduleFooterMarshaller(_)),
- clientEventInfo = timelineModule.clientEventInfo.map(clientEventInfoMarshaller(_)),
- feedbackInfo = timelineModule.feedbackActionInfo.map(feedbackInfoMarshaller(_)),
- metadata = timelineModule.metadata.map(moduleMetadataMarshaller(_)),
- showMoreBehavior = timelineModule.showMoreBehavior.map(moduleShowMoreBehaviorMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala
deleted file mode 100644
index 85d506766..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorOperationMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineOperationMarshaller @Inject() (
- cursorOperationMarshaller: CursorOperationMarshaller) {
-
- def apply(operation: TimelineOperation): urt.TimelineOperation = operation match {
- case cursorOperation: CursorOperation => cursorOperationMarshaller(cursorOperation)
- case _ =>
- throw new UnsupportedTimelineOperationException(operation)
- }
-}
-
-class UnsupportedTimelineOperationException(operation: TimelineOperation)
- extends UnsupportedOperationException(
- "Unsupported timeline operation " + TransportMarshaller.getSimpleName(operation.getClass))
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala
deleted file mode 100644
index a3f495510..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineScribeConfigMarshaller @Inject() () {
-
- def apply(timelineScribeConfig: TimelineScribeConfig): urt.TimelineScribeConfig =
- urt.TimelineScribeConfig(
- page = timelineScribeConfig.page,
- section = timelineScribeConfig.section,
- entityToken = timelineScribeConfig.entityToken
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala
deleted file mode 100644
index d270c3848..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ChildFeedbackActionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackActionMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction
-import com.twitter.timelines.render.thriftscala.TimelineResponse
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * [[TransportMarshaller]] for URT types
- *
- * @note to make an instance of a [[UrtTransportMarshaller]] you can use [[UrtTransportMarshallerBuilder.marshaller]]
- */
-@Singleton
-class UrtTransportMarshaller @Inject() (
- timelineInstructionMarshaller: TimelineInstructionMarshaller,
- feedbackActionMarshaller: FeedbackActionMarshaller,
- childFeedbackActionMarshaller: ChildFeedbackActionMarshaller,
- timelineMetadataMarshaller: TimelineMetadataMarshaller)
- extends TransportMarshaller[Timeline, urt.TimelineResponse] {
-
- override val identifier: TransportMarshallerIdentifier =
- TransportMarshallerIdentifier("UnifiedRichTimeline")
-
- override def apply(timeline: Timeline): urt.TimelineResponse = {
- val feedbackActions: Option[Map[String, urt.FeedbackAction]] = {
- collectAndMarshallFeedbackActions(timeline.instructions)
- }
- urt.TimelineResponse(
- state = urt.TimelineState.Ok,
- timeline = urt.Timeline(
- id = timeline.id,
- instructions = timeline.instructions.map(timelineInstructionMarshaller(_)),
- responseObjects =
- feedbackActions.map(actions => urt.ResponseObjects(feedbackActions = Some(actions))),
- metadata = timeline.metadata.map(timelineMetadataMarshaller(_))
- )
- )
- }
-
- // Currently, feedbackActionInfo at the URT TimelineItem level is supported, which covers almost all
- // existing use cases. However, if additional feedbackActionInfos are defined on the URT
- // TimelineItemContent level for "compound" URT types (see deprecated TopicCollection /
- // TopicCollectionData), this is not supported. If "compound" URT types are added in the future,
- // support must be added within that type (see ModuleItem) to handle the collection and marshalling
- // of these feedbackActionInfos.
-
- private[this] def collectAndMarshallFeedbackActions(
- instructions: Seq[TimelineInstruction]
- ): Option[Map[String, urt.FeedbackAction]] = {
- val feedbackActions: Seq[FeedbackAction] = for {
- feedbackActionInfos <- instructions.collect {
- case c: ContainsFeedbackActionInfos => c.feedbackActionInfos
- }
- feedbackInfoOpt <- feedbackActionInfos
- feedbackInfo <- feedbackInfoOpt.toSeq
- feedbackAction <- feedbackInfo.feedbackActions
- } yield feedbackAction
-
- if (feedbackActions.nonEmpty) {
- val urtFeedbackActions = feedbackActions.map(feedbackActionMarshaller(_))
-
- val urtChildFeedbackActions: Seq[urt.FeedbackAction] = for {
- feedbackAction <- feedbackActions
- childFeedbackActions <- feedbackAction.childFeedbackActions.toSeq
- childFeedbackAction <- childFeedbackActions
- } yield childFeedbackActionMarshaller(childFeedbackAction)
-
- val allUrtFeedbackActions = urtFeedbackActions ++ urtChildFeedbackActions
-
- Some(
- allUrtFeedbackActions.map { urtAction =>
- FeedbackActionMarshaller.generateKey(urtAction) -> urtAction
- }.toMap
- )
- } else {
- None
- }
- }
-}
-
-object UrtTransportMarshaller {
- def unavailable(timelineId: String): TimelineResponse = {
- urt.TimelineResponse(
- state = urt.TimelineState.Unavailable,
- timeline = urt.Timeline(
- id = timelineId,
- instructions = Seq.empty,
- responseObjects = None,
- metadata = None
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala
deleted file mode 100644
index 18447aa35..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala
+++ /dev/null
@@ -1,711 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.ContextualTweetRefMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.OuterTweetContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.TweetHydrationContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level.SafetyLevelMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertColorConfigurationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertDisplayLocationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconDisplayInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertNavigationMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.ButtonStyleMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.CtaButtonMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.IconCtaButtonMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.TextCtaButtonMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorPaletteMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductGroupItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverCtaBehaviorMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverCtaMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverImageMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.FullCoverContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.FullCoverDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.HalfCoverContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.HalfCoverDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleSeedTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space.AudioSpaceItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.SoftInterventionDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryActionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label.IconLabelItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message._
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment.MomentAnnotationItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt._
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingActionTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.TextResultMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.CallToActionTileContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.StandardTileContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFunctionalityTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend.TrendItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TimelinesScoreInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetHighlightsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserReactiveTriggersMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemContentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTileStyleMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTopicTileMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.AspectRatioMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.BroadcastIdMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaEntityMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaKeyMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.RectMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.TweetMediaMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata._
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorDisplayTreatmentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorItemMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorOperationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.AdMetadataContainerMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.CallToActionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.ClickTrackingInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DisclaimerTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DisclosureTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DynamicPrerollTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.MediaInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.SkAdNetworkDataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.SponsorshipTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.UrlOverrideTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.VideoVariantsMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction.TimelineReactionMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.ReferenceObjectMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextAlignmentMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextEntityMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextFormatMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module._
-
-/**
- * Convenience constructor for services not using dependency injection and unit tests. If using
- * dependency injection, instead `@Inject` an instance of [[UrtTransportMarshaller]] to construct.
- */
-object UrtTransportMarshallerBuilder {
- val conversationSectionMarshaller = new ConversationSectionMarshaller
- val conversationDetailsMarshaller = new ConversationDetailsMarshaller(
- conversationSectionMarshaller)
- val timelinesDetailsMarshaller = new TimelinesDetailsMarshaller
- val articleDetailsMarshaller = new ArticleDetailsMarshaller
- val liveEventDetailsMarshaller = new LiveEventDetailsMarshaller
- val commerceDetailsMarshaller = new CommerceDetailsMarshaller
- val clientEventDetailsMarshaller =
- new ClientEventDetailsMarshaller(
- conversationDetailsMarshaller,
- timelinesDetailsMarshaller,
- articleDetailsMarshaller,
- liveEventDetailsMarshaller,
- commerceDetailsMarshaller)
- val clientEventInfoMarshaller = new ClientEventInfoMarshaller(clientEventDetailsMarshaller)
-
- val feedbackTypeMarshaller = new FeedbackTypeMarshaller
- val confirmationDisplayTypeMarshaller = new ConfirmationDisplayTypeMarshaller
- val horizonIconMarshaller = new HorizonIconMarshaller
- val richFeedbackBehaviorMarshaller = new RichFeedbackBehaviorMarshaller
- val childFeedbackActionMarshaller = new ChildFeedbackActionMarshaller(
- feedbackTypeMarshaller = feedbackTypeMarshaller,
- confirmationDisplayTypeMarshaller = confirmationDisplayTypeMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- horizonIconMarshaller = horizonIconMarshaller,
- richFeedbackBehaviorMarshaller = richFeedbackBehaviorMarshaller
- )
- val feedbackActionMarshaller = new FeedbackActionMarshaller(
- childFeedbackActionMarshaller = childFeedbackActionMarshaller,
- feedbackTypeMarshaller = feedbackTypeMarshaller,
- confirmationDisplayTypeMarshaller = confirmationDisplayTypeMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- horizonIconMarshaller = horizonIconMarshaller,
- richFeedbackBehaviorMarshaller = richFeedbackBehaviorMarshaller
- )
- val feedbackDisplayContextMarshaller = new FeedbackDisplayContextMarshaller
- val feedbackInfoMarshaller = new FeedbackInfoMarshaller(
- feedbackActionMarshaller = feedbackActionMarshaller,
- feedbackDisplayContextMarshaller = feedbackDisplayContextMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller
- )
-
- val urlTypeMarshaller = new UrlTypeMarshaller
- val urtEndpointOptionsMarshaller = new UrtEndpointOptionsMarshaller
- val urlMarshaller = new UrlMarshaller(
- urlTypeMarshaller = urlTypeMarshaller,
- urtEndpointOptionsMarshaller = urtEndpointOptionsMarshaller
- )
- val referenceObjectMarshaller = new ReferenceObjectMarshaller(urlMarshaller)
- val richTextFormatMarshaller = new RichTextFormatMarshaller
- val richTextEntityMarshaller =
- new RichTextEntityMarshaller(referenceObjectMarshaller, richTextFormatMarshaller)
- val richTextAlignmentMarshaller = new RichTextAlignmentMarshaller
- val richTextMarshaller =
- new RichTextMarshaller(richTextEntityMarshaller, richTextAlignmentMarshaller)
-
- val tombstoneInfoMarshaller = new TombstoneInfoMarshaller(richTextMarshaller = richTextMarshaller)
-
- val generalContextTypeMarshaller = new GeneralContextTypeMarshaller
- val generalContextMarshaller = new GeneralContextMarshaller(
- generalContextTypeMarshaller = generalContextTypeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val timelineReactionMarshaller = new TimelineReactionMarshaller
-
- val topicContextMarshaller = new TopicContextMarshaller()
-
- val socialContextMarshaller = new SocialContextMarshaller(
- generalContextMarshaller = generalContextMarshaller,
- topicContextMarshaller = topicContextMarshaller
- )
-
- val highlightedSectionMarshaller = new HighlightedSectionMarshaller()
- val tweetHighlightsMarshaller = new TweetHighlightsMarshaller(highlightedSectionMarshaller)
-
- val topicDisplayTypeMarshaller = new TopicDisplayTypeMarshaller
- val topicFunctionalityTypeMarshaller = new TopicFunctionalityTypeMarshaller
- val topicItemMarshaller = new TopicItemMarshaller(
- displayTypeMarshaller = topicDisplayTypeMarshaller,
- functionalityTypeMarshaller = topicFunctionalityTypeMarshaller
- )
-
- val topicFollowPromptDisplayTypeMarshaller = new TopicFollowPromptDisplayTypeMarshaller
- val topicFollowPromptItemMarshaller = new TopicFollowPromptItemMarshaller(
- displayTypeMarshaller = topicFollowPromptDisplayTypeMarshaller
- )
-
- val rosettaColorMarshaller = new RosettaColorMarshaller()
- val badgeMarshaller = new BadgeMarshaller(
- rosettaColorMarshaller = rosettaColorMarshaller
- )
- val iconCtaButtonMarshaller = new IconCtaButtonMarshaller(horizonIconMarshaller, urlMarshaller)
- val textCtaButtonMarshaller = new TextCtaButtonMarshaller(urlMarshaller)
- val ctaButtonMarshaller =
- new CtaButtonMarshaller(iconCtaButtonMarshaller, textCtaButtonMarshaller)
-
- val standardTileContentMarshaller = new StandardTileContentMarshaller(
- badgeMarshaller = badgeMarshaller
- )
- val callToActionTileContentMarshaller = new CallToActionTileContentMarshaller(
- ctaButtonMarshaller = ctaButtonMarshaller,
- richTextMarshaller = richTextMarshaller
- )
-
- val tileContentMarshaller = new TileContentMarshaller(
- standardTileContentMarshaller = standardTileContentMarshaller,
- callToActionTileContentMarshaller = callToActionTileContentMarshaller
- )
- val colorMarshaller = new ColorMarshaller()
- val colorPaletteMarshaller = new ColorPaletteMarshaller(
- colorMarshaller = colorMarshaller
- )
- val imageVariantMarshaller = new ImageVariantMarshaller(
- colorPaletteMarshaller = colorPaletteMarshaller
- )
- val imageDisplayTypeMarshaller = new ImageDisplayTypeMarshaller()
- val imageAnimationTypeMarshaller = new ImageAnimationTypeMarshaller()
-
- val softInterventionDisplayTypeMarshaller = new SoftInterventionDisplayTypeMarshaller
- val forwardPivotDisplayTypeMarshaller = new ForwardPivotDisplayTypeMarshaller
- val forwardPivotMarshaller = new ForwardPivotMarshaller(
- urlMarshaller = urlMarshaller,
- richTextMarshaller = richTextMarshaller,
- forwardPivotDisplayTypeMarshaller = forwardPivotDisplayTypeMarshaller,
- imageVariantMarshaller = imageVariantMarshaller,
- badgeMarshaller = badgeMarshaller,
- rosettaColorMarshaller = rosettaColorMarshaller,
- softInterventionDisplayTypeMarshaller = softInterventionDisplayTypeMarshaller
- )
-
- val tweetDisplayTypeMarshaller = new TweetDisplayTypeMarshaller
- val timelinesScoreInfoMarshaller = new TimelinesScoreInfoMarshaller
- val disclosureTypeMarshaller = new DisclosureTypeMarshaller
- val dynamicPrerollTypeMarshaller = new DynamicPrerollTypeMarshaller
- val callToActionMarshaller = new CallToActionMarshaller
- val videoVariantsMarshaller = new VideoVariantsMarshaller
- val mediaInfoMarshaller = new MediaInfoMarshaller(
- callToActionMarshaller = callToActionMarshaller,
- videoVariantsMarshaller = videoVariantsMarshaller
- )
- val prerollMarshaller = new PrerollMarshaller(
- dynamicPrerollTypeMarshaller = dynamicPrerollTypeMarshaller,
- mediaInfoMarshaller = mediaInfoMarshaller
- )
- val sponsorshipTypeMarshaller = new SponsorshipTypeMarshaller
- val disclaimerTypeMarshaller = new DisclaimerTypeMarshaller
- val skAdNetworkDataMarshaller = new SkAdNetworkDataMarshaller
- val adMetadataContainerMarshaller = new AdMetadataContainerMarshaller(
- sponsorshipTypeMarshaller = sponsorshipTypeMarshaller,
- disclaimerTypeMarshaller = disclaimerTypeMarshaller,
- skAdNetworkDataMarshaller = skAdNetworkDataMarshaller
- )
- val urlOverrideTypeMarshaller = new UrlOverrideTypeMarshaller
- val clickTrackingInfoMarshaller = new ClickTrackingInfoMarshaller(
- urlOverrideTypeMarshaller = urlOverrideTypeMarshaller
- )
- val promotedMetadataMarshaller = new PromotedMetadataMarshaller(
- disclosureTypeMarshaller = disclosureTypeMarshaller,
- adMetadataContainerMarshaller = adMetadataContainerMarshaller,
- clickTrackingInfoMarshaller = clickTrackingInfoMarshaller
- )
-
- val conversationAnnotationTypeMarshaller = new ConversationAnnotationTypeMarshaller
- val conversationAnnotationMarshaller = new ConversationAnnotationMarshaller(
- conversationAnnotationTypeMarshaller = conversationAnnotationTypeMarshaller,
- richTextMarshaller = richTextMarshaller
- )
-
- val safetyLevelMarshaller = new SafetyLevelMarshaller
- val outerTweetContextMarshaller = new OuterTweetContextMarshaller
- val tweetHydrationContextMarshaller = new TweetHydrationContextMarshaller(
- safetyLevelMarshaller = safetyLevelMarshaller,
- outerTweetContextMarshaller = outerTweetContextMarshaller
- )
- val contextualTweetRefMarshaller = new ContextualTweetRefMarshaller(
- tweetHydrationContextMarshaller = tweetHydrationContextMarshaller
- )
- val prerollMetadataMarshaller = new PrerollMetadataMarshaller(
- prerollMarshaller = prerollMarshaller
- )
-
- val rectMarshaller = new RectMarshaller
- val mediaKeyMarshaller = new MediaKeyMarshaller
- val broadcastIdMarshaller = new BroadcastIdMarshaller
- val tweetMediaMarshaller = new TweetMediaMarshaller
- val mediaEntityMarshaller = new MediaEntityMarshaller(
- tweetMediaMarshaller = tweetMediaMarshaller,
- broadcastIdMarshaller = broadcastIdMarshaller,
- imageVariantMarshaller = imageVariantMarshaller)
- val aspectRatioMarshaller = new AspectRatioMarshaller
- val mediaMarshaller = new MediaMarshaller(
- mediaEntityMarshaller = mediaEntityMarshaller,
- mediaKeyMarshaller = mediaKeyMarshaller,
- rectMarshaller = rectMarshaller,
- aspectRatioMarshaller = aspectRatioMarshaller)
-
- val tweetItemMarshaller = new TweetItemMarshaller(
- tweetDisplayTypeMarshaller = tweetDisplayTypeMarshaller,
- socialContextMarshaller = socialContextMarshaller,
- tweetHighlightsMarshaller = tweetHighlightsMarshaller,
- tombstoneInfoMarshaller = tombstoneInfoMarshaller,
- timelinesScoreInfoMarshaller = timelinesScoreInfoMarshaller,
- forwardPivotMarshaller = forwardPivotMarshaller,
- promotedMetadataMarshaller = promotedMetadataMarshaller,
- conversationAnnotationMarshaller = conversationAnnotationMarshaller,
- contextualTweetRefMarshaller = contextualTweetRefMarshaller,
- prerollMetadataMarshaller = prerollMetadataMarshaller,
- badgeMarshaller = badgeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val eventSummaryDisplayTypeMarshaller = new EventSummaryDisplayTypeMarshaller
- val eventSummaryItemMarshaller = new EventSummaryItemMarshaller(
- eventSummaryDisplayTypeMarshaller = eventSummaryDisplayTypeMarshaller,
- imageVariantMarshaller = imageVariantMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val trendItemMarshaller = new TrendItemMarshaller(
- promotedMetadataMarshaller = promotedMetadataMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val userDisplayTypeMarshaller = new UserDisplayTypeMarshaller
- val userReactiveTriggersMarshaller = new UserReactiveTriggersMarshaller(
- timelineReactionMarshaller)
- val userItemMarshaller = new UserItemMarshaller(
- userDisplayTypeMarshaller = userDisplayTypeMarshaller,
- promotedMetadataMarshaller = promotedMetadataMarshaller,
- socialContextMarshaller = socialContextMarshaller,
- userReactiveTriggersMarshaller = userReactiveTriggersMarshaller,
- )
-
- val verticalGridItemTileStyleMarshaller = new VerticalGridItemTileStyleMarshaller
- val verticalGridItemTopicFunctionalityTypeMarshaller =
- new VerticalGridItemTopicFunctionalityTypeMarshaller
-
- val verticalGridItemTopicTileMarshaller = new VerticalGridItemTopicTileMarshaller(
- styleMarshaller = verticalGridItemTileStyleMarshaller,
- functionalityTypeMarshaller = verticalGridItemTopicFunctionalityTypeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val verticalGridItemContentMarshaller = new VerticalGridItemContentMarshaller(
- verticalGridItemTopicTileMarshaller)
-
- val verticalGridItemMarshaller = new VerticalGridItemMarshaller(verticalGridItemContentMarshaller)
-
- val tombstoneDisplayTypeMarshaller = new TombstoneDisplayTypeMarshaller
- val tombstoneItemMarshaller = new TombstoneItemMarshaller(
- displayTypeMarshaller = tombstoneDisplayTypeMarshaller,
- tombstoneInfoMarshaller = tombstoneInfoMarshaller,
- tweetItemMarshaller = tweetItemMarshaller)
-
- val iconLabelItemMarshaller = new IconLabelItemMarshaller(
- richTextMarshaller,
- horizonIconMarshaller
- )
-
- val labelDisplayTypeMarshaller = new LabelDisplayTypeMarshaller
- val labelItemMarshaller = new LabelItemMarshaller(
- displayTypeMarshaller = labelDisplayTypeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val tileItemMarshaller = new TileItemMarshaller(
- tileContentMarshaller = tileContentMarshaller,
- urlMarshaller = urlMarshaller,
- imageVariantMarshaller = imageVariantMarshaller
- )
-
- val callbackMarshaller = new CallbackMarshaller
- val messageActionMarshaller = new MessageActionMarshaller(
- callbackMarshaller,
- clientEventInfoMarshaller
- )
- val messageTextActionMarshaller = new MessageTextActionMarshaller(messageActionMarshaller)
- val messageImageMarshaller = new MessageImageMarshaller(
- imageVariantMarshaller
- )
- val userFacepileDisplayTypeMarshaller = new UserFacepileDisplayTypeMarshaller()
- val messageActionTypeMarshaller = new MessageActionTypeMarshaller()
- val userFacepileMarshaller = new UserFacepileMarshaller(
- messageActionTypeMarshaller,
- messageTextActionMarshaller,
- userFacepileDisplayTypeMarshaller
- )
- val inlinePromptMessageContentMarshaller = new InlinePromptMessageContentMarshaller(
- messageTextActionMarshaller = messageTextActionMarshaller,
- richTextMarshaller = richTextMarshaller,
- socialContextMarshaller = socialContextMarshaller,
- userFacepileMarshaller = userFacepileMarshaller
- )
- val headerImagePromptMessageContentMarshaller = new HeaderImagePromptMessageContentMarshaller(
- messageImageMarshaller = messageImageMarshaller,
- messageTextActionMarshaller = messageTextActionMarshaller,
- messageActionMarshaller = messageActionMarshaller,
- richTextMarshaller = richTextMarshaller
- )
- val compactPromptMessageContentMarshaller = new CompactPromptMessageContentMarshaller(
- messageTextActionMarshaller = messageTextActionMarshaller,
- messageActionMarshaller = messageActionMarshaller,
- richTextMarshaller = richTextMarshaller
- )
- val messageContentMarshaller = new MessageContentMarshaller(
- inlinePromptMessageContentMarshaller = inlinePromptMessageContentMarshaller,
- headerImagePromptMessageContentMarshaller = headerImagePromptMessageContentMarshaller,
- compactPromptMessageContentMarshaller = compactPromptMessageContentMarshaller
- )
- val messagePromptItemMarshaller = new MessagePromptItemMarshaller(
- messageContentMarshaller = messageContentMarshaller,
- callbackMarshaller = callbackMarshaller
- )
-
- val tweetComposerDisplayTypeMarshaller = new TweetComposerDisplayTypeMarshaller
- val tweetComposerItemMarshaller = new TweetComposerItemMarshaller(
- tweetComposerDisplayTypeMarshaller = tweetComposerDisplayTypeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val cursorTypeMarshaller = new CursorTypeMarshaller
- val cursorDisplayTreatmentMarshaller = new CursorDisplayTreatmentMarshaller
- val cursorItemMarshaller = new CursorItemMarshaller(
- cursorTypeMarshaller = cursorTypeMarshaller,
- cursorDisplayTreatmentMarshaller = cursorDisplayTreatmentMarshaller)
- val articleDisplayTypeMarshaller = new ArticleDisplayTypeMarshaller
- val articleSeedTypeMarshaller = new ArticleSeedTypeMarshaller
- val articleItemMarshaller =
- new ArticleItemMarshaller(
- articleDisplayTypeMarshaller,
- socialContextMarshaller,
- articleSeedTypeMarshaller)
- val audioSpaceItemMarshaller = new AudioSpaceItemMarshaller
- val cardDisplayTypeMarshaller = new CardDisplayTypeMarshaller
- val cardItemMarshaller = new CardItemMarshaller(
- cardDisplayTypeMarshaller = cardDisplayTypeMarshaller,
- urlMarshaller = urlMarshaller
- )
-
- val twitterListDisplayTypeMarshaller = new TwitterListDisplayTypeMarshaller
- val twitterListItemMarshaller = new TwitterListItemMarshaller(
- twitterListDisplayTypeMarshaller = twitterListDisplayTypeMarshaller)
-
- val threadHeaderItemMarshaller = new ThreadHeaderItemMarshaller(
- threadHeaderContentMarshaller = new ThreadHeaderContentMarshaller
- )
-
- val relevancePromptFollowUpTextInputMarshaller = new RelevancePromptFollowUpTextInputMarshaller(
- callbackMarshaller = callbackMarshaller
- )
- val relevancePromptFollowUpFeedbackTypeMarshaller =
- new RelevancePromptFollowUpFeedbackTypeMarshaller(
- relevancePromptFollowUpTextInputMarshaller = relevancePromptFollowUpTextInputMarshaller
- )
- val relevancePromptDisplayTypeMarshaller = new RelevancePromptDisplayTypeMarshaller
- val relevancePromptContentMarshaller = new RelevancePromptContentMarshaller(
- callbackMarshaller = callbackMarshaller,
- relevancePromptDisplayTypeMarshaller = relevancePromptDisplayTypeMarshaller,
- relevancePromptFollowUpFeedbackTypeMarshaller = relevancePromptFollowUpFeedbackTypeMarshaller
- )
- val promptContentMarshaller = new PromptContentMarshaller(
- relevancePromptContentMarshaller = relevancePromptContentMarshaller
- )
- val promptItemMarshaller = new PromptItemMarshaller(
- promptContentMarshaller = promptContentMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- callbackMarshaller = callbackMarshaller
- )
-
- val textResultMarshaller = new TextResultMarshaller(highlightedSectionMarshaller)
- val spellingActionTypeMarshaller = new SpellingActionTypeMarshaller()
- val spellingItemMarshaller = new SpellingItemMarshaller(
- textResultMarshaller = textResultMarshaller,
- spellingActionTypeMarshaller = spellingActionTypeMarshaller)
-
- val momentAnnotationItemMarshaller = new MomentAnnotationItemMarshaller(richTextMarshaller)
-
- val genericSummaryDisplayTypeMarshaller = new GenericSummaryDisplayTypeMarshaller
- val genericSummaryActionMarshaller = new GenericSummaryActionMarshaller(
- urlMarshaller = urlMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller)
- val genericSummaryContextMarshaller = new GenericSummaryContextMarshaller(
- richTextMarshaller = richTextMarshaller,
- horizonIconMarshaller = horizonIconMarshaller
- )
- val genericSummaryItemMarshaller = new GenericSummaryItemMarshaller(
- genericSummaryDisplayTypeMarshaller = genericSummaryDisplayTypeMarshaller,
- genericSummaryContextMarshaller = genericSummaryContextMarshaller,
- genericSummaryActionMarshaller = genericSummaryActionMarshaller,
- mediaMarshaller = mediaMarshaller,
- promotedMetadataMarshaller = promotedMetadataMarshaller,
- richTextMarshaller = richTextMarshaller
- )
-
- val commerceProductItemMarshaller = new CommerceProductItemMarshaller
- val commerceProductGroupItemMarshaller = new CommerceProductGroupItemMarshaller
-
- val timelineItemMarshaller = new TimelineItemMarshaller(
- timelineItemContentMarshaller = new TimelineItemContentMarshaller(
- articleItemMarshaller = articleItemMarshaller,
- audioSpaceItemMarshaller = audioSpaceItemMarshaller,
- cardItemMarshaller = cardItemMarshaller,
- cursorItemMarshaller = cursorItemMarshaller,
- eventSummaryItemMarshaller = eventSummaryItemMarshaller,
- iconLabelItemMarshaller = iconLabelItemMarshaller,
- labelItemMarshaller = labelItemMarshaller,
- messagePromptItemMarshaller = messagePromptItemMarshaller,
- tileItemMarshaller = tileItemMarshaller,
- tombstoneItemMarshaller = tombstoneItemMarshaller,
- topicFollowPromptItemMarshaller = topicFollowPromptItemMarshaller,
- topicItemMarshaller = topicItemMarshaller,
- tweetComposerItemMarshaller = tweetComposerItemMarshaller,
- tweetItemMarshaller = tweetItemMarshaller,
- twitterListItemMarshaller = twitterListItemMarshaller,
- userItemMarshaller = userItemMarshaller,
- verticalGridItemMarshaller = verticalGridItemMarshaller,
- threadHeaderItemMarshaller = threadHeaderItemMarshaller,
- promptItemMarshaller = promptItemMarshaller,
- spellingItemMarshaller = spellingItemMarshaller,
- momentAnnotationItemMarshaller = momentAnnotationItemMarshaller,
- genericSummaryItemMarshaller = genericSummaryItemMarshaller,
- commerceProductItemMarshaller = commerceProductItemMarshaller,
- commerceProductGroupItemMarshaller = commerceProductGroupItemMarshaller,
- trendItemMarshaller = trendItemMarshaller
- ),
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- feedbackInfoMarshaller = feedbackInfoMarshaller
- )
-
- val moduleDisplayTypeMarshaller = new ModuleDisplayTypeMarshaller
- val moduleItemTreeDisplayMarshaller =
- new ModuleItemTreeDisplayMarshaller(moduleDisplayTypeMarshaller)
-
- val moduleItemMarshaller = new ModuleItemMarshaller(
- timelineItemMarshaller = timelineItemMarshaller,
- moduleItemTreeDisplayMarshaller = moduleItemTreeDisplayMarshaller)
-
- val moduleHeaderDisplayTypeMarshaller = new ModuleHeaderDisplayTypeMarshaller
- val moduleHeaderMarshaller = new ModuleHeaderMarshaller(
- horizonIconMarshaller = horizonIconMarshaller,
- imageVariantMarshaller = imageVariantMarshaller,
- socialContextMarshaller = socialContextMarshaller,
- moduleHeaderDisplayTypeMarshaller = moduleHeaderDisplayTypeMarshaller
- )
- val moduleFooterMarshaller = new ModuleFooterMarshaller(urlMarshaller = urlMarshaller)
- val adsMetadataMarshaller = new AdsMetadataMarshaller
- val moduleConversationMetadataMarshaller = new ModuleConversationMetadataMarshaller(
- socialContextMarshaller = socialContextMarshaller)
- val gridCarouselMetadataMarshaller = new GridCarouselMetadataMarshaller
- val moduleMetadataMarshaller = new ModuleMetadataMarshaller(
- adsMetadataMarshaller = adsMetadataMarshaller,
- moduleConversationMetadataMarshaller = moduleConversationMetadataMarshaller,
- gridCarouselMetadataMarshaller = gridCarouselMetadataMarshaller
- )
- val moduleShowMoreBehaviorRevealByCountMarshaller =
- new ModuleShowMoreBehaviorRevealByCountMarshaller
- val moduleShowMoreBehaviorMarshaller = new ModuleShowMoreBehaviorMarshaller(
- moduleShowMoreBehaviorRevealByCountMarshaller = moduleShowMoreBehaviorRevealByCountMarshaller
- )
- val timelineModuleMarshaller = new TimelineModuleMarshaller(
- moduleItemMarshaller = moduleItemMarshaller,
- moduleDisplayTypeMarshaller = moduleDisplayTypeMarshaller,
- moduleHeaderMarshaller = moduleHeaderMarshaller,
- moduleFooterMarshaller = moduleFooterMarshaller,
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- feedbackInfoMarshaller = feedbackInfoMarshaller,
- moduleMetadataMarshaller = moduleMetadataMarshaller,
- moduleShowMoreBehaviorMarshaller = moduleShowMoreBehaviorMarshaller
- )
-
- val halfCoverDisplayTypeMarshaller = new HalfCoverDisplayTypeMarshaller()
- val fullCoverDisplayTypeMarshaller = new FullCoverDisplayTypeMarshaller()
- val coverCtaBehaviorMarshaller = new CoverCtaBehaviorMarshaller(richTextMarshaller, urlMarshaller)
- val buttonStyleMarshaller = new ButtonStyleMarshaller()
- val coverCtaMarshaller = new CoverCtaMarshaller(
- coverCtaBehaviorMarshaller,
- callbackMarshaller,
- clientEventInfoMarshaller,
- horizonIconMarshaller,
- buttonStyleMarshaller)
- val coverImageMarshaller =
- new CoverImageMarshaller(
- imageVariantMarshaller,
- imageDisplayTypeMarshaller,
- imageAnimationTypeMarshaller)
- val dismissInfoMarshaller = new DismissInfoMarshaller(callbackMarshaller)
-
- val halfCoverContentMarshaller = new HalfCoverContentMarshaller(
- halfCoverDisplayTypeMarshaller,
- coverCtaMarshaller,
- richTextMarshaller,
- coverImageMarshaller,
- dismissInfoMarshaller,
- callbackMarshaller)
- val fullCoverContentMarshaller = new FullCoverContentMarshaller(
- fullCoverDisplayTypeMarshaller,
- coverCtaMarshaller,
- richTextMarshaller,
- imageVariantMarshaller,
- dismissInfoMarshaller,
- imageDisplayTypeMarshaller,
- callbackMarshaller)
- val coverContentMarshaller =
- new CoverContentMarshaller(fullCoverContentMarshaller, halfCoverContentMarshaller)
- val coverMarshaller = new CoverMarshaller(coverContentMarshaller, clientEventInfoMarshaller)
-
- val cursorOperationMarshaller = new CursorOperationMarshaller(
- cursorTypeMarshaller = cursorTypeMarshaller,
- cursorDisplayTreatmentMarshaller = cursorDisplayTreatmentMarshaller)
- val timelineOperationMarshaller = new TimelineOperationMarshaller(
- cursorOperationMarshaller = cursorOperationMarshaller)
-
- val timelineEntryMarshaller = new TimelineEntryMarshaller(
- timelineEntryContentMarshaller = new TimelineEntryContentMarshaller(
- timelineItemMarshaller = timelineItemMarshaller,
- timelineModuleMarshaller = timelineModuleMarshaller,
- timelineOperationMarshaller = timelineOperationMarshaller))
-
- val addEntriesInstructionMarshaller = new AddEntriesInstructionMarshaller(
- timelineEntryMarshaller = timelineEntryMarshaller)
-
- val markEntriesUnreadInstructionMarshaller = new MarkEntriesUnreadInstructionMarshaller()
-
- val addToModuleInstructionMarshaller = new AddToModuleInstructionMarshaller(
- moduleItemMarshaller = moduleItemMarshaller)
-
- val replaceEntryInstructionMarshaller = new ReplaceEntryInstructionMarshaller(
- timelineEntryMarshaller = timelineEntryMarshaller
- )
-
- val pinEntryInstructionMarshaller = new PinEntryInstructionMarshaller(
- timelineEntryMarshaller = timelineEntryMarshaller
- )
-
- val showAlertTypeMarshaller = new ShowAlertTypeMarshaller()
- val showAlertIconMarshaller = new ShowAlertIconMarshaller()
- val showAlertIconDisplayInfoMarshaller = new ShowAlertIconDisplayInfoMarshaller(
- showAlertIconMarshaller = showAlertIconMarshaller,
- rosettaColorMarshaller = rosettaColorMarshaller
- )
- val showAlertColorConfigurationMarshaller = new ShowAlertColorConfigurationMarshaller(
- rosettaColorMarshaller = rosettaColorMarshaller
- )
- val showAlertDisplayLocationMarshaller = new ShowAlertDisplayLocationMarshaller()
- val showAlertNavigationMetadataMarshaller = new ShowAlertNavigationMetadataMarshaller()
- val showAlertInstructionMarshaller = new ShowAlertInstructionMarshaller(
- showAlertTypeMarshaller = new ShowAlertTypeMarshaller(),
- clientEventInfoMarshaller = clientEventInfoMarshaller,
- richTextMarshaller = richTextMarshaller,
- showAlertIconDisplayInfoMarshaller = showAlertIconDisplayInfoMarshaller,
- showAlertColorConfigurationMarshaller = showAlertColorConfigurationMarshaller,
- showAlertDisplayLocationMarshaller = showAlertDisplayLocationMarshaller,
- showAlertNavigationMetadataMarshaller = showAlertNavigationMetadataMarshaller
- )
-
- val timelineInstructionMarshaller = new TimelineInstructionMarshaller(
- addEntriesInstructionMarshaller = addEntriesInstructionMarshaller,
- addToModuleInstructionMarshaller = addToModuleInstructionMarshaller,
- markEntriesUnreadInstructionMarshaller = markEntriesUnreadInstructionMarshaller,
- pinEntryInstructionMarshaller = pinEntryInstructionMarshaller,
- replaceEntryInstructionMarshaller = replaceEntryInstructionMarshaller,
- showAlertInstructionMarshaller = showAlertInstructionMarshaller,
- terminateTimelineInstructionMarshaller = new TerminateTimelineInstructionMarshaller,
- coverMarshaller = coverMarshaller,
- )
-
- val timelineScribeConfigMarshaller = new TimelineScribeConfigMarshaller
-
- val readerModeConfigMarshaller = new ReaderModeConfigMarshaller(urlMarshaller)
-
- val timelineMetadataMarshaller = new TimelineMetadataMarshaller(
- timelineScribeConfigMarshaller = timelineScribeConfigMarshaller,
- readerModeConfigMarshaller = readerModeConfigMarshaller
- )
-
- val marshaller: UrtTransportMarshaller =
- new UrtTransportMarshaller(
- timelineInstructionMarshaller = timelineInstructionMarshaller,
- feedbackActionMarshaller = feedbackActionMarshaller,
- childFeedbackActionMarshaller = childFeedbackActionMarshaller,
- timelineMetadataMarshaller = timelineMetadataMarshaller
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD
deleted file mode 100644
index 62f1b9de1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- "util/util-core:util-core-util",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- "util/util-core:util-core-util",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala
deleted file mode 100644
index e1b5cb7f1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class ShowAlertColorConfigurationMarshaller @Inject() (
- rosettaColorMarshaller: RosettaColorMarshaller) {
-
- def apply(colorConfiguration: ShowAlertColorConfiguration): urt.ShowAlertColorConfiguration =
- urt.ShowAlertColorConfiguration(
- background = rosettaColorMarshaller(colorConfiguration.background),
- text = rosettaColorMarshaller(colorConfiguration.text),
- border = colorConfiguration.border.map(rosettaColorMarshaller(_)),
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala
deleted file mode 100644
index 8e7c979cb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Top
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Bottom
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class ShowAlertDisplayLocationMarshaller @Inject() () {
-
- def apply(alertDisplayLocation: ShowAlertDisplayLocation): urt.ShowAlertDisplayLocation =
- alertDisplayLocation match {
- case Top => urt.ShowAlertDisplayLocation.Top
- case Bottom => urt.ShowAlertDisplayLocation.Bottom
- }
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala
deleted file mode 100644
index 9be91f48b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo
-
-@Singleton
-class ShowAlertIconDisplayInfoMarshaller @Inject() (
- showAlertIconMarshaller: ShowAlertIconMarshaller,
- rosettaColorMarshaller: RosettaColorMarshaller,
-) {
-
- def apply(alertIconDisplayInfo: ShowAlertIconDisplayInfo): urt.ShowAlertIconDisplayInfo =
- urt.ShowAlertIconDisplayInfo(
- icon = showAlertIconMarshaller(alertIconDisplayInfo.icon),
- tint = rosettaColorMarshaller(alertIconDisplayInfo.tint),
- )
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala
deleted file mode 100644
index 91cef4d86..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.DownArrow
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.UpArrow
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class ShowAlertIconMarshaller @Inject() () {
-
- def apply(alertIcon: ShowAlertIcon): urt.ShowAlertIcon = alertIcon match {
- case UpArrow => urt.ShowAlertIcon.UpArrow
- case DownArrow => urt.ShowAlertIcon.DownArrow
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala
deleted file mode 100644
index f8daff191..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ShowAlertNavigationMetadataMarshaller @Inject() () {
-
- def apply(alertNavigationMetadata: ShowAlertNavigationMetadata): urt.ShowAlertNavigationMetadata =
- urt.ShowAlertNavigationMetadata(navigateToEntryId =
- Some(alertNavigationMetadata.navigateToEntryId))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala
deleted file mode 100644
index 83ae14c3f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Navigate
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.NewTweets
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ShowAlertTypeMarshaller @Inject() () {
-
- def apply(alertType: ShowAlertType): urt.AlertType = alertType match {
- case NewTweets => urt.AlertType.NewTweets
- case Navigate => urt.AlertType.Navigate
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD
deleted file mode 100644
index 43ea49f65..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala
deleted file mode 100644
index 3676b2d56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Default
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Primary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Secondary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Text
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Destructive
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Neutral
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveSecondary
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveText
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ButtonStyleMarshaller @Inject() () {
- def apply(buttonStyle: ButtonStyle): urt.ButtonStyle =
- buttonStyle match {
- case Default => urt.ButtonStyle.Default
- case Primary => urt.ButtonStyle.Primary
- case Secondary => urt.ButtonStyle.Secondary
- case Text => urt.ButtonStyle.Text
- case Destructive => urt.ButtonStyle.Destructive
- case Neutral => urt.ButtonStyle.Neutral
- case DestructiveSecondary => urt.ButtonStyle.DestructiveSecondary
- case DestructiveText => urt.ButtonStyle.DestructiveText
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala
deleted file mode 100644
index 936b9073e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.CtaButton
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.IconCtaButton
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.TextCtaButton
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CtaButtonMarshaller @Inject() (
- iconCtaButtonMarshaller: IconCtaButtonMarshaller,
- textCtaButtonMarshaller: TextCtaButtonMarshaller) {
-
- def apply(ctaButton: CtaButton): urt.CtaButton = ctaButton match {
- case button: TextCtaButton => urt.CtaButton.Text(textCtaButtonMarshaller(button))
- case button: IconCtaButton => urt.CtaButton.Icon(iconCtaButtonMarshaller(button))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala
deleted file mode 100644
index c22c3666a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.IconCtaButton
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class IconCtaButtonMarshaller @Inject() (
- horizonIconMarshaller: HorizonIconMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(iconCtaButton: IconCtaButton): urt.IconCtaButton =
- urt.IconCtaButton(
- buttonIcon = horizonIconMarshaller(iconCtaButton.buttonIcon),
- accessibilityLabel = iconCtaButton.accessibilityLabel,
- url = urlMarshaller(iconCtaButton.url)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala
deleted file mode 100644
index f805a1758..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.TextCtaButton
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TextCtaButtonMarshaller @Inject() (
- urlMarshaller: UrlMarshaller) {
-
- def apply(textCtaButton: TextCtaButton): urt.TextCtaButton =
- urt.TextCtaButton(
- buttonText = textCtaButton.buttonText,
- url = urlMarshaller(textCtaButton.url)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD
deleted file mode 100644
index 7e72e4f60..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala
deleted file mode 100644
index 98eacd8d8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.Color
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Singleton
-
-@Singleton
-class ColorMarshaller {
-
- def apply(color: Color): urt.Color = urt.Color(
- red = color.red,
- green = color.green,
- blue = color.blue,
- opacity = color.opacity
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala
deleted file mode 100644
index 22a932aa3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ColorPalette
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ColorPaletteMarshaller @Inject() (
- colorMarshaller: ColorMarshaller) {
-
- def apply(colorPalette: ColorPalette): urt.ColorPaletteItem = urt.ColorPaletteItem(
- rgb = colorMarshaller(colorPalette.rgb),
- percentage = colorPalette.percentage
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala
deleted file mode 100644
index 91926673e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RosettaColorMarshaller @Inject() () {
-
- def apply(rosettaColor: RosettaColor): urt.RosettaColor = rosettaColor match {
- case WhiteRosettaColor => urt.RosettaColor.White
- case BlackRosettaColor => urt.RosettaColor.Black
- case ClearRosettaColor => urt.RosettaColor.Clear
- case TextBlackRosettaColor => urt.RosettaColor.TextBlack
- case TextBlueRosettaColor => urt.RosettaColor.TextBlue
- case DeepGrayRosettaColor => urt.RosettaColor.DeepGray
- case MediumGrayRosettaColor => urt.RosettaColor.MediumGray
- case LightGrayRosettaColor => urt.RosettaColor.LightGray
- case FadedGrayRosettaColor => urt.RosettaColor.FadedGray
- case FaintGrayRosettaColor => urt.RosettaColor.FaintGray
- case DeepOrangeRosettaColor => urt.RosettaColor.DeepOrange
- case MediumOrangeRosettaColor => urt.RosettaColor.MediumOrange
- case LightOrangeRosettaColor => urt.RosettaColor.LightOrange
- case FadedOrangeRosettaColor => urt.RosettaColor.FadedOrange
- case DeepYellowRosettaColor => urt.RosettaColor.DeepYellow
- case MediumYellowRosettaColor => urt.RosettaColor.MediumYellow
- case LightYellowRosettaColor => urt.RosettaColor.LightYellow
- case FadedYellowRosettaColor => urt.RosettaColor.FadedYellow
- case DeepGreenRosettaColor => urt.RosettaColor.DeepGreen
- case MediumGreenRosettaColor => urt.RosettaColor.MediumGreen
- case LightGreenRosettaColor => urt.RosettaColor.LightGreen
- case FadedGreenRosettaColor => urt.RosettaColor.FadedGreen
- case DeepBlueRosettaColor => urt.RosettaColor.DeepBlue
- case TwitterBlueRosettaColor => urt.RosettaColor.TwitterBlue
- case LightBlueRosettaColor => urt.RosettaColor.LightBlue
- case FadedBlueRosettaColor => urt.RosettaColor.FadedBlue
- case FaintBlueRosettaColor => urt.RosettaColor.FaintBlue
- case DeepPurpleRosettaColor => urt.RosettaColor.DeepPurple
- case MediumPurpleRosettaColor => urt.RosettaColor.MediumPurple
- case LightPurpleRosettaColor => urt.RosettaColor.LightPurple
- case FadedPurpleRosettaColor => urt.RosettaColor.FadedPurple
- case DeepRedRosettaColor => urt.RosettaColor.DeepRed
- case MediumRedRosettaColor => urt.RosettaColor.MediumRed
- case LightRedRosettaColor => urt.RosettaColor.LightRed
- case FadedRedRosettaColor => urt.RosettaColor.FadedRed
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD
deleted file mode 100644
index abb1600e9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala
deleted file mode 100644
index 3841420e9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CoverContentMarshaller @Inject() (
- fullCoverContentMarshaller: FullCoverContentMarshaller,
- halfCoverContentMarshaller: HalfCoverContentMarshaller) {
-
- def apply(coverContent: CoverContent): urt.Cover = coverContent match {
- case fullCover: FullCoverContent => fullCoverContentMarshaller(fullCover)
- case halfCover: HalfCoverContent => halfCoverContentMarshaller(halfCover)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala
deleted file mode 100644
index ae5c49228..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCtaBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorDismiss
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorNavigate
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-
-@Singleton
-class CoverCtaBehaviorMarshaller @Inject() (
- richTextMarshaller: RichTextMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(coverCtaBehavior: CoverCtaBehavior): urt.CoverCtaBehavior =
- coverCtaBehavior match {
- case dismiss: CoverBehaviorDismiss =>
- urt.CoverCtaBehavior.Dismiss(
- urt.CoverBehaviorDismiss(dismiss.feedbackMessage.map(richTextMarshaller(_))))
- case nav: CoverBehaviorNavigate =>
- urt.CoverCtaBehavior.Navigate(urt.CoverBehaviorNavigate(urlMarshaller(nav.url)))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala
deleted file mode 100644
index c46196cfa..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.ButtonStyleMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCta
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CoverCtaMarshaller @Inject() (
- coverCtaBehaviorMarshaller: CoverCtaBehaviorMarshaller,
- callbackMarshaller: CallbackMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- horizonIconMarshaller: HorizonIconMarshaller,
- buttonStyleMarshaller: ButtonStyleMarshaller) {
-
- def apply(coverCta: CoverCta): urt.CoverCta = urt.CoverCta(
- text = coverCta.text,
- ctaBehavior = coverCtaBehaviorMarshaller(coverCta.ctaBehavior),
- callbacks = coverCta.callbacks.map(_.map(callbackMarshaller(_))),
- clientEventInfo = coverCta.clientEventInfo.map(clientEventInfoMarshaller(_)),
- icon = coverCta.icon.map(horizonIconMarshaller(_)),
- buttonStyle = coverCta.buttonStyle.map(buttonStyleMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala
deleted file mode 100644
index b04fa0faf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageAnimationTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverImage
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CoverImageMarshaller @Inject() (
- imageVariantMarshaller: ImageVariantMarshaller,
- imageDisplayTypeMarshaller: ImageDisplayTypeMarshaller,
- imageAnimationTypeMarshaller: ImageAnimationTypeMarshaller) {
-
- def apply(coverImage: CoverImage): urt.CoverImage =
- urt.CoverImage(
- image = imageVariantMarshaller(coverImage.imageVariant),
- imageDisplayType = imageDisplayTypeMarshaller(coverImage.imageDisplayType),
- imageAnimationType = coverImage.imageAnimationType.map(imageAnimationTypeMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala
deleted file mode 100644
index 3ec88a87a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.DismissInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageDisplayTypeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FullCoverContentMarshaller @Inject() (
- fullCoverDisplayTypeMarshaller: FullCoverDisplayTypeMarshaller,
- coverCtaMarshaller: CoverCtaMarshaller,
- richTextMarshaller: RichTextMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller,
- dismissInfoMarshaller: DismissInfoMarshaller,
- imageDisplayTypeMarshaller: ImageDisplayTypeMarshaller,
- callbackMarshaller: CallbackMarshaller) {
-
- def apply(fullCover: FullCoverContent): urt.Cover =
- urt.Cover.FullCover(
- urt.FullCover(
- displayType = fullCoverDisplayTypeMarshaller(fullCover.displayType),
- primaryText = richTextMarshaller(fullCover.primaryText),
- primaryCoverCta = coverCtaMarshaller(fullCover.primaryCoverCta),
- secondaryCoverCta = fullCover.secondaryCoverCta.map(coverCtaMarshaller(_)),
- secondaryText = fullCover.secondaryText.map(richTextMarshaller(_)),
- image = fullCover.imageVariant.map(imageVariantMarshaller(_)),
- details = fullCover.details.map(richTextMarshaller(_)),
- dismissInfo = fullCover.dismissInfo.map(dismissInfoMarshaller(_)),
- imageDisplayType = fullCover.imageDisplayType.map(imageDisplayTypeMarshaller(_)),
- impressionCallbacks = fullCover.impressionCallbacks.map(_.map(callbackMarshaller(_)))
- ))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala
deleted file mode 100644
index 9a961c925..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverFullCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FullCoverDisplayTypeMarshaller @Inject() () {
-
- def apply(halfCoverDisplayType: FullCoverDisplayType): urt.FullCoverDisplayType =
- halfCoverDisplayType match {
- case CoverFullCoverDisplayType => urt.FullCoverDisplayType.Cover
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala
deleted file mode 100644
index 35f45b27e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.DismissInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HalfCoverContentMarshaller @Inject() (
- halfCoverDisplayTypeMarshaller: HalfCoverDisplayTypeMarshaller,
- coverCtaMarshaller: CoverCtaMarshaller,
- richTextMarshaller: RichTextMarshaller,
- coverImageMarshaller: CoverImageMarshaller,
- dismissInfoMarshaller: DismissInfoMarshaller,
- callbackMarshaller: CallbackMarshaller) {
-
- def apply(halfCover: HalfCoverContent): urt.Cover =
- urt.Cover.HalfCover(
- urt.HalfCover(
- displayType = halfCoverDisplayTypeMarshaller(halfCover.displayType),
- primaryText = richTextMarshaller(halfCover.primaryText),
- primaryCoverCta = coverCtaMarshaller(halfCover.primaryCoverCta),
- secondaryCoverCta = halfCover.secondaryCoverCta.map(coverCtaMarshaller(_)),
- secondaryText = halfCover.secondaryText.map(richTextMarshaller(_)),
- impressionCallbacks = halfCover.impressionCallbacks.map(_.map(callbackMarshaller(_))),
- dismissible = halfCover.dismissible,
- coverImage = halfCover.coverImage.map(coverImageMarshaller(_)),
- dismissInfo = halfCover.dismissInfo.map(dismissInfoMarshaller(_))
- ))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala
deleted file mode 100644
index 537d2faf2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CenterCoverHalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HalfCoverDisplayTypeMarshaller @Inject() () {
-
- def apply(halfCoverDisplayType: HalfCoverDisplayType): urt.HalfCoverDisplayType =
- halfCoverDisplayType match {
- case CenterCoverHalfCoverDisplayType => urt.HalfCoverDisplayType.CenterCover
- case CoverHalfCoverDisplayType => urt.HalfCoverDisplayType.Cover
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD
deleted file mode 100644
index 83a9b306f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala
deleted file mode 100644
index e3d71ff5c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HorizonIconMarshaller @Inject() () {
-
- def apply(icon: HorizonIcon): urt.HorizonIcon = icon match {
- case Bookmark => urt.HorizonIcon.Bookmark
- case Moment => urt.HorizonIcon.Moment
- case Debug => urt.HorizonIcon.Debug
- case Error => urt.HorizonIcon.Error
- case Follow => urt.HorizonIcon.Follow
- case Unfollow => urt.HorizonIcon.Unfollow
- case Smile => urt.HorizonIcon.Smile
- case Frown => urt.HorizonIcon.Frown
- case Help => urt.HorizonIcon.Help
- case Link => urt.HorizonIcon.Link
- case Message => urt.HorizonIcon.Message
- case No => urt.HorizonIcon.No
- case Outgoing => urt.HorizonIcon.Outgoing
- case Pin => urt.HorizonIcon.Pin
- case Retweet => urt.HorizonIcon.Retweet
- case Speaker => urt.HorizonIcon.Speaker
- case Trashcan => urt.HorizonIcon.Trashcan
- case Feedback => urt.HorizonIcon.Feedback
- case FeedbackClose => urt.HorizonIcon.FeedbackClose
- case EyeOff => urt.HorizonIcon.EyeOff
- case Moderation => urt.HorizonIcon.Moderation
- case Topic => urt.HorizonIcon.Topic
- case TopicClose => urt.HorizonIcon.TopicClose
- case Flag => urt.HorizonIcon.Flag
- case TopicFilled => urt.HorizonIcon.TopicFilled
- case NotificationsFollow => urt.HorizonIcon.NotificationsFollow
- case Person => urt.HorizonIcon.Person
- case BalloonStroke => urt.HorizonIcon.BalloonStroke
- case Calendar => urt.HorizonIcon.Calendar
- case LocationStroke => urt.HorizonIcon.LocationStroke
- case PersonStroke => urt.HorizonIcon.PersonStroke
- case Safety => urt.HorizonIcon.Safety
- case Logo => urt.HorizonIcon.Logo
- case SparkleOn => urt.HorizonIcon.SparkleOn
- case StarRising => urt.HorizonIcon.StarRising
- case CameraVideo => urt.HorizonIcon.CameraVideo
- case ShoppingClock => urt.HorizonIcon.ShoppingClock
- case ArrowRight => urt.HorizonIcon.ArrowRight
- case SpeakerOff => urt.HorizonIcon.SpeakerOff
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD
deleted file mode 100644
index c0ffc860c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-scala_library(
- sources = ["**/*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala
deleted file mode 100644
index 8ff49b5e2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.Default
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ArticleDisplayTypeMarshaller @Inject() () {
- def apply(articleDisplayType: ArticleDisplayType): urt.ArticleDisplayType =
- articleDisplayType match {
- case Default => urt.ArticleDisplayType.Default
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala
deleted file mode 100644
index 35c931d79..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ArticleItemMarshaller @Inject() (
- articleDisplayTypeMarshaller: ArticleDisplayTypeMarshaller,
- socialContextMarshaller: SocialContextMarshaller,
- articleSeedTypeMarshaller: ArticleSeedTypeMarshaller) {
- def apply(articleItem: ArticleItem): urt.TimelineItemContent =
- urt.TimelineItemContent.Article(
- urt.Article(
- id = articleItem.id,
- displayType = articleItem.displayType.map(articleDisplayTypeMarshaller(_)),
- socialContext = articleItem.socialContext.map(socialContextMarshaller(_)),
- articleSeedType = Some(articleSeedTypeMarshaller(articleItem.articleSeedType))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala
deleted file mode 100644
index 0227f8057..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleSeedType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FriendsOfFriendsSeed
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ListIdSeed
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ArticleSeedTypeMarshaller @Inject() () {
-
- def apply(articleSeedType: ArticleSeedType): urt.ArticleSeedType =
- articleSeedType match {
- case FollowingListSeed => urt.ArticleSeedType.FollowingList
- case FriendsOfFriendsSeed => urt.ArticleSeedType.FriendsOfFriends
- case ListIdSeed => urt.ArticleSeedType.ListId
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala
deleted file mode 100644
index b9a75756b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AudioSpaceItemMarshaller @Inject() () {
-
- def apply(audioSpaceItem: AudioSpaceItem): urt.TimelineItemContent =
- urt.TimelineItemContent.AudioSpace(
- urt.AudioSpace(
- id = audioSpaceItem.id
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala
deleted file mode 100644
index 3565b6aba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card._
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class CardDisplayTypeMarshaller @Inject() () {
-
- def apply(cardDisplayType: CardDisplayType): urt.CardDisplayType = cardDisplayType match {
- case HeroDisplayType => urt.CardDisplayType.Hero
- case CellDisplayType => urt.CardDisplayType.Cell
- case TweetCardDisplayType => urt.CardDisplayType.TweetCard
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala
deleted file mode 100644
index 2ae8008bf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CardItemMarshaller @Inject() (
- cardDisplayTypeMarshaller: CardDisplayTypeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(cardItem: CardItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Card(
- urt.Card(
- cardUrl = cardItem.cardUrl,
- text = cardItem.text,
- subtext = cardItem.subtext,
- url = cardItem.url.map(urlMarshaller(_)),
- cardDisplayType = cardItem.displayType.map(cardDisplayTypeMarshaller(_))
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala
deleted file mode 100644
index 5fd0b9d56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CommerceProductGroupItemMarshaller @Inject() () {
-
- def apply(commerceProductGroupItem: CommerceProductGroupItem): urt.TimelineItemContent =
- urt.TimelineItemContent.CommerceProductGroup(
- urt.CommerceProductGroup(commerceProductGroupItem.id))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala
deleted file mode 100644
index 8bc08beae..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CommerceProductItemMarshaller @Inject() () {
-
- def apply(commerceProductItem: CommerceProductItem): urt.TimelineItemContent =
- urt.TimelineItemContent.CommerceProduct(urt.CommerceProduct(commerceProductItem.id))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala
deleted file mode 100644
index bed51192e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConversationAnnotationMarshaller @Inject() (
- conversationAnnotationTypeMarshaller: ConversationAnnotationTypeMarshaller,
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(conversationAnnotation: ConversationAnnotation): urt.ConversationAnnotation = {
- urt.ConversationAnnotation(
- conversationAnnotationType =
- conversationAnnotationTypeMarshaller(conversationAnnotation.conversationAnnotationType),
- header = conversationAnnotation.header.map(richTextMarshaller(_)),
- description = conversationAnnotation.description.map(richTextMarshaller(_))
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala
deleted file mode 100644
index 85488d061..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotationType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.Large
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.Political
-
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConversationAnnotationTypeMarshaller @Inject() () {
-
- def apply(
- conversationAnnotationType: ConversationAnnotationType
- ): urt.ConversationAnnotationType = conversationAnnotationType match {
- case Large => urt.ConversationAnnotationType.Large
- case Political => urt.ConversationAnnotationType.Political
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala
deleted file mode 100644
index 3b325d822..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.CellEventSummaryDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.HeroEventSummaryDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.CellWithProminentSocialContextEventSummaryDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class EventSummaryDisplayTypeMarshaller @Inject() () {
-
- def apply(
- eventSummaryDisplayType: EventSummaryDisplayType
- ): urt.EventSummaryDisplayType = eventSummaryDisplayType match {
- case CellEventSummaryDisplayType =>
- urt.EventSummaryDisplayType.Cell
- case HeroEventSummaryDisplayType =>
- urt.EventSummaryDisplayType.Hero
- case CellWithProminentSocialContextEventSummaryDisplayType =>
- urt.EventSummaryDisplayType.CellWithProminentSocialContext
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala
deleted file mode 100644
index 0aa7b2471..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class EventSummaryItemMarshaller @Inject() (
- eventSummaryDisplayTypeMarshaller: EventSummaryDisplayTypeMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(eventSummary: EventSummaryItem): urt.TimelineItemContent =
- urt.TimelineItemContent.EventSummary(
- urt.EventSummary(
- id = eventSummary.id,
- title = eventSummary.title,
- displayType = eventSummaryDisplayTypeMarshaller(eventSummary.displayType),
- url = urlMarshaller(eventSummary.url),
- image = eventSummary.image.map(imageVariantMarshaller(_)),
- timeString = eventSummary.timeString
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala
deleted file mode 100644
index 648d8fb87..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.CommunityNotes
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivotDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.LiveEvent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.SoftIntervention
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ForwardPivotDisplayTypeMarshaller @Inject() () {
-
- def apply(forwardPivotDisplayType: ForwardPivotDisplayType): urt.ForwardPivotDisplayType =
- forwardPivotDisplayType match {
- case LiveEvent => urt.ForwardPivotDisplayType.LiveEvent
- case SoftIntervention => urt.ForwardPivotDisplayType.SoftIntervention
- case CommunityNotes => urt.ForwardPivotDisplayType.CommunityNotes
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala
deleted file mode 100644
index 6ef392c95..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ForwardPivotMarshaller @Inject() (
- urlMarshaller: UrlMarshaller,
- richTextMarshaller: RichTextMarshaller,
- forwardPivotDisplayTypeMarshaller: ForwardPivotDisplayTypeMarshaller,
- softInterventionDisplayTypeMarshaller: SoftInterventionDisplayTypeMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller,
- badgeMarshaller: BadgeMarshaller,
- rosettaColorMarshaller: RosettaColorMarshaller) {
-
- def apply(forwardPivot: ForwardPivot): urt.ForwardPivot = urt.ForwardPivot(
- text = richTextMarshaller(forwardPivot.text),
- landingUrl = urlMarshaller(forwardPivot.landingUrl),
- displayType = forwardPivotDisplayTypeMarshaller(forwardPivot.displayType),
- iconImageVariant = forwardPivot.iconImageVariant.map(imageVariantMarshaller(_)),
- stateBadge = forwardPivot.stateBadge.map(badgeMarshaller(_)),
- subtext = forwardPivot.subtext.map(richTextMarshaller(_)),
- backgroundColorName = forwardPivot.backgroundColorName.map(rosettaColorMarshaller(_)),
- engagementNudge = forwardPivot.engagementNudge,
- softInterventionDisplayType =
- forwardPivot.softInterventionDisplayType.map(softInterventionDisplayTypeMarshaller(_)),
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala
deleted file mode 100644
index e2bf9dc34..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.GetTheLatest
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.GovernmentRequested
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.Misleading
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.SoftInterventionDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.StayInformed
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SoftInterventionDisplayTypeMarshaller @Inject() () {
-
- def apply(
- softInterventionDisplayType: SoftInterventionDisplayType
- ): urt.SoftInterventionDisplayType =
- softInterventionDisplayType match {
- case GetTheLatest => urt.SoftInterventionDisplayType.GetTheLatest
- case StayInformed => urt.SoftInterventionDisplayType.StayInformed
- case Misleading => urt.SoftInterventionDisplayType.Misleading
- case GovernmentRequested => urt.SoftInterventionDisplayType.GovernmentRequested
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala
deleted file mode 100644
index ff5ff44d6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GenericSummaryActionMarshaller @Inject() (
- urlMarshaller: UrlMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(genericSummaryItemAction: GenericSummaryAction): urt.GenericSummaryAction =
- urt.GenericSummaryAction(
- url = urlMarshaller(genericSummaryItemAction.url),
- clientEventInfo = genericSummaryItemAction.clientEventInfo.map(clientEventInfoMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala
deleted file mode 100644
index 67401cbba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryContext
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GenericSummaryContextMarshaller @Inject() (
- richTextMarshaller: RichTextMarshaller,
- horizonIconMarshaller: HorizonIconMarshaller) {
-
- def apply(genericSummaryItemContext: GenericSummaryContext): urt.GenericSummaryContext =
- urt.GenericSummaryContext(
- text = richTextMarshaller(genericSummaryItemContext.text),
- icon = genericSummaryItemContext.icon.map(horizonIconMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala
deleted file mode 100644
index 293736390..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItemDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.HeroDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GenericSummaryDisplayTypeMarshaller @Inject() () {
-
- def apply(
- genericSummaryItemDisplayType: GenericSummaryItemDisplayType
- ): urt.GenericSummaryDisplayType =
- genericSummaryItemDisplayType match {
- case HeroDisplayType => urt.GenericSummaryDisplayType.Hero
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala
deleted file mode 100644
index 0717a5c34..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GenericSummaryItemMarshaller @Inject() (
- genericSummaryDisplayTypeMarshaller: GenericSummaryDisplayTypeMarshaller,
- genericSummaryContextMarshaller: GenericSummaryContextMarshaller,
- genericSummaryActionMarshaller: GenericSummaryActionMarshaller,
- mediaMarshaller: MediaMarshaller,
- promotedMetadataMarshaller: PromotedMetadataMarshaller,
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(genericSummaryItem: GenericSummaryItem): urt.TimelineItemContent =
- urt.TimelineItemContent.GenericSummary(
- urt.GenericSummary(
- headline = richTextMarshaller(genericSummaryItem.headline),
- displayType = genericSummaryDisplayTypeMarshaller(genericSummaryItem.displayType),
- userAttributionIds = genericSummaryItem.userAttributionIds,
- media = genericSummaryItem.media.map(mediaMarshaller(_)),
- context = genericSummaryItem.context.map(genericSummaryContextMarshaller(_)),
- timestamp = genericSummaryItem.timestamp.map(_.inMilliseconds),
- onClickAction = genericSummaryItem.onClickAction.map(genericSummaryActionMarshaller(_)),
- promotedMetadata = genericSummaryItem.promotedMetadata.map(promotedMetadataMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala
deleted file mode 100644
index a370e7a9b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HighlightedSectionMarshaller @Inject() () {
-
- def apply(highlightedSection: HighlightedSection): urt.HighlightedSection =
- urt.HighlightedSection(
- startIndex = highlightedSection.startIndex,
- endIndex = highlightedSection.endIndex
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala
deleted file mode 100644
index c6830185c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class IconLabelItemMarshaller @Inject() (
- richTextMarshaller: RichTextMarshaller,
- horizonIconMarshaller: HorizonIconMarshaller) {
-
- def apply(iconLabelItem: IconLabelItem): urt.TimelineItemContent =
- urt.TimelineItemContent.IconLabel(
- urt.IconLabel(
- text = richTextMarshaller(iconLabelItem.text),
- icon = iconLabelItem.icon.map(horizonIconMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala
deleted file mode 100644
index 119c6adf7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LabelDisplayTypeMarshaller @Inject() () {
-
- def apply(labelDisplayType: LabelDisplayType): urt.LabelDisplayType = labelDisplayType match {
- case InlineHeaderLabelDisplayType => urt.LabelDisplayType.InlineHeader
- case OtherRepliesSectionHeaderLabelDisplayType => urt.LabelDisplayType.OtherRepliesSectionHeader
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala
deleted file mode 100644
index 10dae7f8a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label.LabelItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LabelItemMarshaller @Inject() (
- displayTypeMarshaller: LabelDisplayTypeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(labelItem: LabelItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Label(
- urt.Label(
- text = labelItem.text,
- subtext = labelItem.subtext,
- disclosureIndicator = labelItem.disclosureIndicator,
- url = labelItem.url.map(urlMarshaller(_)),
- displayType = labelItem.displayType.map(displayTypeMarshaller(_))
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala
deleted file mode 100644
index c40867874..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CompactPromptMessageContentMarshaller @Inject() (
- messageTextActionMarshaller: MessageTextActionMarshaller,
- messageActionMarshaller: MessageActionMarshaller,
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(compactPromptMessageContent: CompactPromptMessageContent): urt.MessageContent =
- urt.MessageContent.CompactPrompt(
- urt.CompactPrompt(
- headerText = compactPromptMessageContent.headerText,
- bodyText = compactPromptMessageContent.bodyText,
- primaryButtonAction =
- compactPromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)),
- secondaryButtonAction =
- compactPromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)),
- action = compactPromptMessageContent.action.map(messageActionMarshaller(_)),
- headerRichText = compactPromptMessageContent.headerRichText.map(richTextMarshaller(_)),
- bodyRichText = compactPromptMessageContent.bodyRichText.map(richTextMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala
deleted file mode 100644
index ba3abac35..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class HeaderImagePromptMessageContentMarshaller @Inject() (
- messageImageMarshaller: MessageImageMarshaller,
- messageTextActionMarshaller: MessageTextActionMarshaller,
- messageActionMarshaller: MessageActionMarshaller,
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(
- headerImagePromptMessageContent: HeaderImagePromptMessageContent
- ): urt.MessageContent =
- urt.MessageContent.HeaderImagePrompt(
- urt.HeaderImagePrompt(
- headerImage = messageImageMarshaller(headerImagePromptMessageContent.headerImage),
- headerText = headerImagePromptMessageContent.headerText,
- bodyText = headerImagePromptMessageContent.bodyText,
- primaryButtonAction =
- headerImagePromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)),
- secondaryButtonAction =
- headerImagePromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)),
- action = headerImagePromptMessageContent.action.map(messageActionMarshaller(_)),
- headerRichText = headerImagePromptMessageContent.headerRichText.map(richTextMarshaller(_)),
- bodyRichText = headerImagePromptMessageContent.bodyRichText.map(richTextMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala
deleted file mode 100644
index e33830dbb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class InlinePromptMessageContentMarshaller @Inject() (
- messageTextActionMarshaller: MessageTextActionMarshaller,
- richTextMarshaller: RichTextMarshaller,
- socialContextMarshaller: SocialContextMarshaller,
- userFacepileMarshaller: UserFacepileMarshaller) {
-
- def apply(inlinePromptMessageContent: InlinePromptMessageContent): urt.MessageContent =
- urt.MessageContent.InlinePrompt(
- urt.InlinePrompt(
- headerText = inlinePromptMessageContent.headerText,
- bodyText = inlinePromptMessageContent.bodyText,
- primaryButtonAction =
- inlinePromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)),
- secondaryButtonAction =
- inlinePromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)),
- headerRichText = inlinePromptMessageContent.headerRichText.map(richTextMarshaller(_)),
- bodyRichText = inlinePromptMessageContent.bodyRichText.map(richTextMarshaller(_)),
- socialContext = inlinePromptMessageContent.socialContext.map(socialContextMarshaller(_)),
- userFacepile = inlinePromptMessageContent.userFacepile.map(userFacepileMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala
deleted file mode 100644
index ca8612585..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageActionMarshaller @Inject() (
- callbackMarshaller: CallbackMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(messageAction: MessageAction): urt.MessageAction = {
-
- urt.MessageAction(
- dismissOnClick = messageAction.dismissOnClick,
- url = messageAction.url,
- clientEventInfo = messageAction.clientEventInfo.map(clientEventInfoMarshaller(_)),
- onClickCallbacks =
- messageAction.onClickCallbacks.map(callbackList => callbackList.map(callbackMarshaller(_)))
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala
deleted file mode 100644
index dde02b150..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.FollowAllMessageActionType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageActionTypeMarshaller @Inject() () {
-
- def apply(messageActionType: MessageActionType): urt.MessageActionType = messageActionType match {
- case FollowAllMessageActionType => urt.MessageActionType.FollowAll
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala
deleted file mode 100644
index 01f1501ad..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageContentMarshaller @Inject() (
- inlinePromptMessageContentMarshaller: InlinePromptMessageContentMarshaller,
- headerImagePromptMessageContentMarshaller: HeaderImagePromptMessageContentMarshaller,
- compactPromptMessageContentMarshaller: CompactPromptMessageContentMarshaller) {
-
- def apply(messageContent: MessageContent): urt.MessageContent = messageContent match {
- case inlinePromptMessageContent: InlinePromptMessageContent =>
- inlinePromptMessageContentMarshaller(inlinePromptMessageContent)
- case headerImagePromptMessageContent: HeaderImagePromptMessageContent =>
- headerImagePromptMessageContentMarshaller(headerImagePromptMessageContent)
- case compactPromptMessageContent: CompactPromptMessageContent =>
- compactPromptMessageContentMarshaller(compactPromptMessageContent)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala
deleted file mode 100644
index c10a26903..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageImage
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageImageMarshaller @Inject() (
- imageVariantMarshaller: ImageVariantMarshaller) {
-
- def apply(messageImage: MessageImage): urt.MessageImage = {
- urt.MessageImage(
- imageVariants = messageImage.imageVariants.map(imageVariantMarshaller(_)),
- backgroundColor = messageImage.backgroundColor
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala
deleted file mode 100644
index a5a4a3a77..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessagePromptItemMarshaller @Inject() (
- messageContentMarshaller: MessageContentMarshaller,
- callbackMarshaller: CallbackMarshaller) {
-
- def apply(messagePromptItem: MessagePromptItem): urt.TimelineItemContent =
- urt.TimelineItemContent.Message(
- urt.MessagePrompt(
- content = messageContentMarshaller(messagePromptItem.content),
- impressionCallbacks = messagePromptItem.impressionCallbacks.map { callbackList =>
- callbackList.map(callbackMarshaller(_))
- }
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala
deleted file mode 100644
index f7a21d6e1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MessageTextActionMarshaller @Inject() (
- messageActionMarshaller: MessageActionMarshaller) {
-
- def apply(messageTextAction: MessageTextAction): urt.MessageTextAction =
- urt.MessageTextAction(
- text = messageTextAction.text,
- action = messageActionMarshaller(messageTextAction.action)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala
deleted file mode 100644
index 9c7d39f0c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.LargeUserFacepileDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactUserFacepileDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepileDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UserFacepileDisplayTypeMarshaller @Inject() () {
-
- def apply(userFacepileDisplayType: UserFacepileDisplayType): urt.UserFacepileDisplayType =
- userFacepileDisplayType match {
- case LargeUserFacepileDisplayType => urt.UserFacepileDisplayType.Large
- case CompactUserFacepileDisplayType => urt.UserFacepileDisplayType.Compact
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala
deleted file mode 100644
index c6f5dabc8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UserFacepileMarshaller @Inject() (
- messageActionTypeMarshaller: MessageActionTypeMarshaller,
- messageTextActionMarshaller: MessageTextActionMarshaller,
- userFacepileDisplayTypeMarshaller: UserFacepileDisplayTypeMarshaller) {
-
- def apply(userFacepile: UserFacepile): urt.UserFacepile =
- urt.UserFacepile(
- userIds = userFacepile.userIds,
- featuredUserIds = userFacepile.featuredUserIds,
- action = userFacepile.action.map(messageTextActionMarshaller(_)),
- actionType = userFacepile.actionType.map(messageActionTypeMarshaller(_)),
- displaysFeaturingText = userFacepile.displaysFeaturingText,
- displayType = userFacepile.displayType.map(userFacepileDisplayTypeMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala
deleted file mode 100644
index 59f33f3d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MomentAnnotationItemMarshaller @Inject() (richTextMarshaller: RichTextMarshaller) {
- def apply(momentAnnotationItem: MomentAnnotationItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.MomentAnnotation(
- urt.MomentAnnotation(
- annotationId = momentAnnotationItem.id,
- text = momentAnnotationItem.text.map(richTextMarshaller(_)),
- header = momentAnnotationItem.header.map(richTextMarshaller(_)),
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala
deleted file mode 100644
index 9b669dd04..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PromptContentMarshaller @Inject() (
- relevancePromptContentMarshaller: RelevancePromptContentMarshaller) {
-
- def apply(promptContent: PromptContent): urt.PromptContent = promptContent match {
- case relevancePromptContent: RelevancePromptContent =>
- urt.PromptContent.RelevancePrompt(relevancePromptContentMarshaller(relevancePromptContent))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala
deleted file mode 100644
index ccefd082b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PromptItemMarshaller @Inject() (
- promptContentMarshaller: PromptContentMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- callbackMarshaller: CallbackMarshaller) {
-
- def apply(relevancePromptItem: PromptItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Prompt(
- urt.Prompt(
- content = promptContentMarshaller(relevancePromptItem.content),
- clientEventInfo = relevancePromptItem.clientEventInfo.map(clientEventInfoMarshaller(_)),
- impressionCallbacks = relevancePromptItem.impressionCallbacks.map { callbackList =>
- callbackList.map(callbackMarshaller(_))
- }
- ))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala
deleted file mode 100644
index be5d87003..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RelevancePromptContentMarshaller @Inject() (
- callbackMarshaller: CallbackMarshaller,
- relevancePromptDisplayTypeMarshaller: RelevancePromptDisplayTypeMarshaller,
- relevancePromptFollowUpFeedbackTypeMarshaller: RelevancePromptFollowUpFeedbackTypeMarshaller) {
-
- def apply(relevancePromptContent: RelevancePromptContent): urt.RelevancePrompt =
- urt.RelevancePrompt(
- title = relevancePromptContent.title,
- confirmation = relevancePromptContent.confirmation,
- isRelevantText = relevancePromptContent.isRelevantText,
- notRelevantText = relevancePromptContent.notRelevantText,
- isRelevantCallback = callbackMarshaller(relevancePromptContent.isRelevantCallback),
- notRelevantCallback = callbackMarshaller(relevancePromptContent.notRelevantCallback),
- displayType = relevancePromptDisplayTypeMarshaller(relevancePromptContent.displayType),
- isRelevantFollowUp = relevancePromptContent.isRelevantFollowUp.map(
- relevancePromptFollowUpFeedbackTypeMarshaller(_)),
- notRelevantFollowUp = relevancePromptContent.notRelevantFollowUp.map(
- relevancePromptFollowUpFeedbackTypeMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala
deleted file mode 100644
index f81247e95..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Singleton
-
-@Singleton
-class RelevancePromptDisplayTypeMarshaller {
-
- def apply(
- relevancePromptDisplayType: RelevancePromptDisplayType
- ): urt.RelevancePromptDisplayType = relevancePromptDisplayType match {
- case Normal => urt.RelevancePromptDisplayType.Normal
- case Compact => urt.RelevancePromptDisplayType.Compact
- case Large => urt.RelevancePromptDisplayType.Large
- case ThumbsUpAndDown => urt.RelevancePromptDisplayType.ThumbsUpAndDown
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala
deleted file mode 100644
index 8b01c14f6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RelevancePromptFollowUpFeedbackTypeMarshaller @Inject() (
- relevancePromptFollowUpTextInputMarshaller: RelevancePromptFollowUpTextInputMarshaller) {
-
- def apply(
- relevancePromptFollowUpFeedbackType: RelevancePromptFollowUpFeedbackType
- ): urt.RelevancePromptFollowUpFeedbackType = relevancePromptFollowUpFeedbackType match {
- case relevancePromptFollowUpTextInput: RelevancePromptFollowUpTextInput =>
- urt.RelevancePromptFollowUpFeedbackType.FollowUpTextInput(
- relevancePromptFollowUpTextInputMarshaller(relevancePromptFollowUpTextInput))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala
deleted file mode 100644
index d244e628f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptFollowUpTextInput
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RelevancePromptFollowUpTextInputMarshaller @Inject() (
- callbackMarshaller: CallbackMarshaller) {
-
- def apply(
- relevancePromptFollowUpTextInput: RelevancePromptFollowUpTextInput
- ): urt.RelevancePromptFollowUpTextInput = urt.RelevancePromptFollowUpTextInput(
- context = relevancePromptFollowUpTextInput.context,
- textFieldPlaceholder = relevancePromptFollowUpTextInput.textFieldPlaceholder,
- sendTextCallback = callbackMarshaller(relevancePromptFollowUpTextInput.sendTextCallback)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala
deleted file mode 100644
index 737c8e3ff..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Singleton
-
-@Singleton
-class SpellingActionTypeMarshaller {
-
- def apply(spellingActionType: SpellingActionType): urt.SpellingActionType =
- spellingActionType match {
- case ReplaceSpellingActionType => urt.SpellingActionType.Replace
- case ExpandSpellingActionType => urt.SpellingActionType.Expand
- case SuggestSpellingActionType => urt.SpellingActionType.Suggest
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala
deleted file mode 100644
index 4e0afe10c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SpellingItemMarshaller @Inject() (
- textResultMarshaller: TextResultMarshaller,
- spellingActionTypeMarshaller: SpellingActionTypeMarshaller) {
-
- def apply(spellingItem: SpellingItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Spelling(
- urt.Spelling(
- spellingResult = textResultMarshaller(spellingItem.textResult),
- spellingAction = spellingItem.spellingActionType.map(spellingActionTypeMarshaller(_)),
- originalQuery = spellingItem.originalQuery
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala
deleted file mode 100644
index 44c353b48..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.TextResult
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TextResultMarshaller @Inject() (highlightedSectionMarshaller: HighlightedSectionMarshaller) {
-
- def apply(textResult: TextResult): urt.TextResult = {
- val hitHighlights = textResult.hitHighlights.map {
- highlightedSections: Seq[HighlightedSection] =>
- highlightedSections.map(highlightedSectionMarshaller(_))
- }
-
- urt.TextResult(
- text = textResult.text,
- hitHighlights = hitHighlights,
- score = textResult.score,
- querySource = textResult.querySource)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala
deleted file mode 100644
index de79fe4e8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ThreadHeaderContentMarshaller @Inject() () {
- def apply(content: ThreadHeaderContent): urt.ThreadHeaderContent = content match {
- case UserThreadHeader(userId) =>
- urt.ThreadHeaderContent.UserThreadHeader(urt.UserThreadHeader(userId))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala
deleted file mode 100644
index 8d88d7d33..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread.ThreadHeaderItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ThreadHeaderItemMarshaller @Inject() (
- threadHeaderContentMarshaller: ThreadHeaderContentMarshaller) {
-
- def apply(threadHeaderItem: ThreadHeaderItem): urt.TimelineItemContent.ThreadHeader =
- urt.TimelineItemContent.ThreadHeader(
- urt.ThreadHeaderItem(
- content = threadHeaderContentMarshaller(threadHeaderItem.content)
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala
deleted file mode 100644
index 52e92691b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.CtaButtonMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CallToActionTileContentMarshaller @Inject() (
- ctaButtonMarshaller: CtaButtonMarshaller,
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(callToActionTileContent: CallToActionTileContent): urt.TileContentCallToAction =
- urt.TileContentCallToAction(
- text = callToActionTileContent.text,
- richText = callToActionTileContent.richText.map(richTextMarshaller(_)),
- ctaButton = callToActionTileContent.ctaButton.map(ctaButtonMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala
deleted file mode 100644
index 042f9dc69..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class StandardTileContentMarshaller @Inject() (
- badgeMarshaller: BadgeMarshaller) {
-
- def apply(standardTileContent: StandardTileContent): urt.TileContentStandard =
- urt.TileContentStandard(
- title = standardTileContent.title,
- supportingText = standardTileContent.supportingText,
- badge = standardTileContent.badge.map(badgeMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala
deleted file mode 100644
index 2688a9e4d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileContent
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TileContentMarshaller @Inject() (
- standardTileContentMarshaller: StandardTileContentMarshaller,
- callToActionTileContentMarshaller: CallToActionTileContentMarshaller) {
-
- def apply(tileContent: TileContent): urt.TileContent = tileContent match {
- case tileCont: StandardTileContent =>
- urt.TileContent.Standard(standardTileContentMarshaller(tileCont))
- case tileCont: CallToActionTileContent =>
- urt.TileContent.CallToAction(callToActionTileContentMarshaller(tileCont))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala
deleted file mode 100644
index e926568cc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TileItemMarshaller @Inject() (
- tileContentMarshaller: TileContentMarshaller,
- urlMarshaller: UrlMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller) {
-
- def apply(tileItem: TileItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Tile(
- urt.Tile(
- title = tileItem.title,
- supportingText = tileItem.supportingText,
- url = tileItem.url.map(urlMarshaller(_)),
- image = tileItem.image.map(imageVariantMarshaller(_)),
- badge = None,
- content = tileContentMarshaller(tileItem.content)
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala
deleted file mode 100644
index 323e2a429..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.DisconnectedRepliesAncestor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.DisconnectedRepliesDescendant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.Inline
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.NonCompliant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TweetUnavailable
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TombstoneDisplayTypeMarshaller @Inject() () {
-
- def apply(tombstoneDisplayType: TombstoneDisplayType): urt.TombstoneDisplayType =
- tombstoneDisplayType match {
- case TweetUnavailable => urt.TombstoneDisplayType.TweetUnavailable
- case DisconnectedRepliesAncestor => urt.TombstoneDisplayType.DisconnectedRepliesAncestor
- case DisconnectedRepliesDescendant => urt.TombstoneDisplayType.DisconnectedRepliesDescendant
- case Inline => urt.TombstoneDisplayType.Inline
- case NonCompliant => urt.TombstoneDisplayType.NonCompliant
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala
deleted file mode 100644
index 0a996eee6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TombstoneInfoMarshaller @Inject() (
- richTextMarshaller: RichTextMarshaller) {
-
- def apply(tombstoneInfo: TombstoneInfo): urt.TombstoneInfo = urt.TombstoneInfo(
- text = tombstoneInfo.text,
- richText = tombstoneInfo.richText.map(richTextMarshaller(_)),
- richRevealText = tombstoneInfo.richRevealText.map(richTextMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala
deleted file mode 100644
index 6cc94b38c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TombstoneItemMarshaller @Inject() (
- displayTypeMarshaller: TombstoneDisplayTypeMarshaller,
- tombstoneInfoMarshaller: TombstoneInfoMarshaller,
- tweetItemMarshaller: TweetItemMarshaller) {
-
- def apply(tombstoneItem: TombstoneItem): urt.TimelineItemContent =
- urt.TimelineItemContent.Tombstone(
- urt.Tombstone(
- displayType = displayTypeMarshaller(tombstoneItem.tombstoneDisplayType),
- tombstoneInfo = tombstoneItem.tombstoneInfo.map(tombstoneInfoMarshaller(_)),
- tweet = tombstoneItem.tweet.map(tweetItemMarshaller(_).tweet)
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala
deleted file mode 100644
index eb8d0187e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.NoIconTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillTopicDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillWithoutActionIconDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicDisplayTypeMarshaller @Inject() () {
-
- def apply(topicDisplayType: TopicDisplayType): urt.TopicDisplayType = topicDisplayType match {
- case BasicTopicDisplayType => urt.TopicDisplayType.Basic
- case PillTopicDisplayType => urt.TopicDisplayType.Pill
- case NoIconTopicDisplayType => urt.TopicDisplayType.NoIcon
- case PillWithoutActionIconDisplayType => urt.TopicDisplayType.PillWithoutActionIcon
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala
deleted file mode 100644
index 97bed21f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.IncentiveFocusTopicFollowPromptDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFocusTopicFollowPromptDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicFollowPromptDisplayTypeMarshaller @Inject() () {
-
- def apply(
- topicFollowPromptDisplayType: TopicFollowPromptDisplayType
- ): urt.TopicFollowPromptDisplayType =
- topicFollowPromptDisplayType match {
- case IncentiveFocusTopicFollowPromptDisplayType =>
- urt.TopicFollowPromptDisplayType.IncentiveFocus
- case TopicFocusTopicFollowPromptDisplayType => urt.TopicFollowPromptDisplayType.TopicFocus
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala
deleted file mode 100644
index 05ebe46f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicFollowPromptItemMarshaller @Inject() (
- displayTypeMarshaller: TopicFollowPromptDisplayTypeMarshaller) {
-
- def apply(topicFollowPromptItem: TopicFollowPromptItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.TopicFollowPrompt(
- urt.TopicFollowPrompt(
- topicId = topicFollowPromptItem.id.toString,
- displayType = displayTypeMarshaller(topicFollowPromptItem.topicFollowPromptDisplayType),
- followIncentiveTitle = topicFollowPromptItem.followIncentiveTitle,
- followIncentiveText = topicFollowPromptItem.followIncentiveText
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala
deleted file mode 100644
index 4646c37a1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PivotTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.RecommendationTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicFunctionalityTypeMarshaller @Inject() () {
-
- def apply(topicFunctionalityType: TopicFunctionalityType): urt.TopicFunctionalityType =
- topicFunctionalityType match {
- case BasicTopicFunctionalityType => urt.TopicFunctionalityType.Basic
- case RecommendationTopicFunctionalityType => urt.TopicFunctionalityType.Recommendation
- case PivotTopicFunctionalityType => urt.TopicFunctionalityType.Pivot
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala
deleted file mode 100644
index ad43d16a7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicItemMarshaller @Inject() (
- displayTypeMarshaller: TopicDisplayTypeMarshaller,
- functionalityTypeMarshaller: TopicFunctionalityTypeMarshaller) {
-
- def apply(topicItem: TopicItem): urt.TimelineItemContent = {
- urt.TimelineItemContent.Topic(
- urt.Topic(
- topicId = topicItem.id.toString,
- topicDisplayType = topicItem.topicDisplayType
- .map(displayTypeMarshaller(_)).getOrElse(urt.TopicDisplayType.Basic),
- topicFunctionalityType = topicItem.topicFunctionalityType
- .map(functionalityTypeMarshaller(_)).getOrElse(urt.TopicFunctionalityType.Basic),
- // This is currently not required by users of this library
- reactiveTriggers = None
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala
deleted file mode 100644
index 0386c5fa8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem
-import com.twitter.timelines.render.thriftscala.GroupedTrend
-import com.twitter.timelines.render.thriftscala.TrendMetadata
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class TrendItemMarshaller @Inject() (
- promotedMetadataMarshaller: PromotedMetadataMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(trendItem: TrendItem): urt.TimelineItemContent =
- urt.TimelineItemContent.Trend(
- urt.Trend(
- name = trendItem.trendName,
- url = urlMarshaller(trendItem.url),
- promotedMetadata = trendItem.promotedMetadata.map(promotedMetadataMarshaller(_)),
- description = trendItem.description,
- trendMetadata = Some(
- TrendMetadata(
- metaDescription = trendItem.metaDescription,
- url = Some(urlMarshaller(trendItem.url)),
- domainContext = trendItem.domainContext
- )),
- groupedTrends = trendItem.groupedTrends.map { trends =>
- trends.map { trend =>
- GroupedTrend(name = trend.trendName, url = urlMarshaller(trend.url))
- }
- }
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala
deleted file mode 100644
index 53f75b716..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TimelinesScoreInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelinesScoreInfoMarshaller @Inject() () {
-
- def apply(timelinesScoreInfo: TimelinesScoreInfo): urt.TimelinesScoreInfo =
- urt.TimelinesScoreInfo(score = timelinesScoreInfo.score)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala
deleted file mode 100644
index 734dec577..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetDisplayTypeMarshaller @Inject() () {
-
- def apply(tweetDisplayType: TweetDisplayType): urt.TweetDisplayType = tweetDisplayType match {
- case Tweet => urt.TweetDisplayType.Tweet
- case TweetFollowOnly => urt.TweetDisplayType.TweetFollowOnly
- case Media => urt.TweetDisplayType.Media
- case MomentTimelineTweet => urt.TweetDisplayType.MomentTimelineTweet
- case EmphasizedPromotedTweet => urt.TweetDisplayType.EmphasizedPromotedTweet
- case QuotedTweet => urt.TweetDisplayType.QuotedTweet
- case SelfThread => urt.TweetDisplayType.SelfThread
- case CompactPromotedTweet => urt.TweetDisplayType.CompactPromotedTweet
- case TweetWithoutCard => urt.TweetDisplayType.TweetWithoutCard
- case ReaderModeRoot => urt.TweetDisplayType.ReaderModeRoot
- case ReaderMode => urt.TweetDisplayType.ReaderMode
- case CondensedTweet => urt.TweetDisplayType.CondensedTweet
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala
deleted file mode 100644
index 10026f7ac..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetHighlights
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetHighlightsMarshaller @Inject() (
- highlightedSectionMarshaller: HighlightedSectionMarshaller) {
-
- def apply(tweetHighlights: TweetHighlights): urt.TweetHighlights =
- urt.TweetHighlights(
- textHighlights = tweetHighlights.textHighlights
- .map(_.map(highlightedSectionMarshaller(_))),
- cardTitleHighlights = tweetHighlights.cardTitleHighlights
- .map(_.map(highlightedSectionMarshaller(_))),
- cardDescriptionHighlights = tweetHighlights.cardDescriptionHighlights
- .map(_.map(highlightedSectionMarshaller(_)))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala
deleted file mode 100644
index ee5222e4f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.ContextualTweetRefMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneInfoMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMetadataMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetItemMarshaller @Inject() (
- tweetDisplayTypeMarshaller: TweetDisplayTypeMarshaller,
- socialContextMarshaller: SocialContextMarshaller,
- tweetHighlightsMarshaller: TweetHighlightsMarshaller,
- tombstoneInfoMarshaller: TombstoneInfoMarshaller,
- timelinesScoreInfoMarshaller: TimelinesScoreInfoMarshaller,
- forwardPivotMarshaller: ForwardPivotMarshaller,
- promotedMetadataMarshaller: PromotedMetadataMarshaller,
- conversationAnnotationMarshaller: ConversationAnnotationMarshaller,
- contextualTweetRefMarshaller: ContextualTweetRefMarshaller,
- prerollMetadataMarshaller: PrerollMetadataMarshaller,
- badgeMarshaller: BadgeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(tweetItem: TweetItem): urt.TimelineItemContent.Tweet = urt.TimelineItemContent.Tweet(
- urt.Tweet(
- id = tweetItem.id,
- displayType = tweetDisplayTypeMarshaller(tweetItem.displayType),
- socialContext = tweetItem.socialContext.map(socialContextMarshaller(_)),
- highlights = tweetItem.highlights.map(tweetHighlightsMarshaller(_)),
- innerTombstoneInfo = tweetItem.innerTombstoneInfo.map(tombstoneInfoMarshaller(_)),
- timelinesScoreInfo = tweetItem.timelinesScoreInfo.map(timelinesScoreInfoMarshaller(_)),
- hasModeratedReplies = tweetItem.hasModeratedReplies,
- forwardPivot = tweetItem.forwardPivot.map(forwardPivotMarshaller(_)),
- innerForwardPivot = tweetItem.innerForwardPivot.map(forwardPivotMarshaller(_)),
- promotedMetadata = tweetItem.promotedMetadata.map(promotedMetadataMarshaller(_)),
- conversationAnnotation =
- tweetItem.conversationAnnotation.map(conversationAnnotationMarshaller(_)),
- contextualTweetRef = tweetItem.contextualTweetRef.map(contextualTweetRefMarshaller(_)),
- prerollMetadata = tweetItem.prerollMetadata.map(prerollMetadataMarshaller(_)),
- replyBadge = tweetItem.replyBadge.map(badgeMarshaller(_)),
- destination = tweetItem.destination.map(urlMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala
deleted file mode 100644
index 1d0817ea4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.Reply
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerSelfThread
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetComposerDisplayTypeMarshaller @Inject() () {
-
- def apply(displayType: TweetComposerDisplayType): urt.TweetComposerDisplayType =
- displayType match {
- case TweetComposerSelfThread => urt.TweetComposerDisplayType.SelfThread
- case Reply => urt.TweetComposerDisplayType.Reply
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala
deleted file mode 100644
index 8d018a9b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetComposerItemMarshaller @Inject() (
- tweetComposerDisplayTypeMarshaller: TweetComposerDisplayTypeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(tweetComposer: TweetComposerItem): urt.TimelineItemContent =
- urt.TimelineItemContent.TweetComposer(
- urt.TweetComposer(
- displayType = tweetComposerDisplayTypeMarshaller(tweetComposer.displayType),
- text = tweetComposer.text,
- url = urlMarshaller(tweetComposer.url)
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala
deleted file mode 100644
index 3ee2e3611..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.List
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListTile
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListWithPin
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListWithSubscribe
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TwitterListDisplayTypeMarshaller @Inject() () {
-
- def apply(twitterListDisplayType: TwitterListDisplayType): urt.TwitterListDisplayType =
- twitterListDisplayType match {
- case List => urt.TwitterListDisplayType.List
- case ListTile => urt.TwitterListDisplayType.ListTile
- case ListWithPin => urt.TwitterListDisplayType.ListWithPin
- case ListWithSubscribe => urt.TwitterListDisplayType.ListWithSubscribe
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala
deleted file mode 100644
index 9331ce0f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TwitterListItemMarshaller @Inject() (
- twitterListDisplayTypeMarshaller: TwitterListDisplayTypeMarshaller) {
-
- def apply(twitterListItem: TwitterListItem): urt.TimelineItemContent =
- urt.TimelineItemContent.TwitterList(
- urt.TwitterList(
- id = twitterListItem.id,
- displayType = twitterListItem.displayType.map(twitterListDisplayTypeMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala
deleted file mode 100644
index 2f2c18da2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.PendingFollowUser
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDetailed
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UserDisplayTypeMarshaller @Inject() () {
-
- def apply(userDisplayType: UserDisplayType): urt.UserDisplayType =
- userDisplayType match {
- case User => urt.UserDisplayType.User
- case UserDetailed => urt.UserDisplayType.UserDetailed
- case PendingFollowUser => urt.UserDisplayType.PendingFollowUser
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala
deleted file mode 100644
index d48b59d02..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UserItemMarshaller @Inject() (
- userDisplayTypeMarshaller: UserDisplayTypeMarshaller,
- promotedMetadataMarshaller: PromotedMetadataMarshaller,
- socialContextMarshaller: SocialContextMarshaller,
- userReactiveTriggersMarshaller: UserReactiveTriggersMarshaller) {
-
- def apply(userItem: UserItem): urt.TimelineItemContent =
- urt.TimelineItemContent.User(
- urt.User(
- id = userItem.id,
- displayType = userDisplayTypeMarshaller(userItem.displayType),
- promotedMetadata = userItem.promotedMetadata.map(promotedMetadataMarshaller(_)),
- socialContext = userItem.socialContext.map(socialContextMarshaller(_)),
- enableReactiveBlending = userItem.enableReactiveBlending,
- reactiveTriggers = userItem.reactiveTriggers.map(userReactiveTriggersMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala
deleted file mode 100644
index 35eb891d8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction.TimelineReactionMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserReactiveTriggers
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UserReactiveTriggersMarshaller @Inject() (
- timelineReactionMarshaller: TimelineReactionMarshaller) {
-
- def apply(userReactiveTriggers: UserReactiveTriggers): urt.UserReactiveTriggers = {
- urt.UserReactiveTriggers(
- onFollow = userReactiveTriggers.onFollow.map(timelineReactionMarshaller(_)))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala
deleted file mode 100644
index 396df8570..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class VerticalGridItemContentMarshaller @Inject() (
- verticalGridItemTopicTileMarshaller: VerticalGridItemTopicTileMarshaller) {
-
- def apply(item: VerticalGridItem): urt.VerticalGridItemContent = item match {
- case verticalGridItemTopicTile: VerticalGridItemTopicTile =>
- verticalGridItemTopicTileMarshaller(verticalGridItemTopicTile)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala
deleted file mode 100644
index 4955fae5c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class VerticalGridItemMarshaller @Inject() (
- verticalGridItemContentMarshaller: VerticalGridItemContentMarshaller) {
-
- def apply(verticalGridItem: VerticalGridItem): urt.TimelineItemContent =
- urt.TimelineItemContent.VerticalGridItem(
- urt.VerticalGridItem(
- content = verticalGridItemContentMarshaller(verticalGridItem)
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala
deleted file mode 100644
index b0db79567..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.SingleStateDefaultVerticalGridItemTileStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.DoubleStateDefaultVerticalGridItemTileStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTileStyle
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class VerticalGridItemTileStyleMarshaller @Inject() () {
-
- def apply(verticalGridItemTileStyle: VerticalGridItemTileStyle): urt.VerticalGridItemTileStyle =
- verticalGridItemTileStyle match {
- case SingleStateDefaultVerticalGridItemTileStyle =>
- urt.VerticalGridItemTileStyle.SingleStateDefault
- case DoubleStateDefaultVerticalGridItemTileStyle =>
- urt.VerticalGridItemTileStyle.DoubleStateDefault
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala
deleted file mode 100644
index e31a11d14..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.PivotVerticalGridItemTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.RecommendationVerticalGridItemTopicFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class VerticalGridItemTopicFunctionalityTypeMarshaller @Inject() () {
-
- def apply(
- verticalGridItemTopicFunctionalityType: VerticalGridItemTopicFunctionalityType
- ): urt.VerticalGridItemTopicFunctionalityType = verticalGridItemTopicFunctionalityType match {
- case PivotVerticalGridItemTopicFunctionalityType =>
- urt.VerticalGridItemTopicFunctionalityType.Pivot
- case RecommendationVerticalGridItemTopicFunctionalityType =>
- urt.VerticalGridItemTopicFunctionalityType.Recommendation
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala
deleted file mode 100644
index 4a67ad0ed..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class VerticalGridItemTopicTileMarshaller @Inject() (
- styleMarshaller: VerticalGridItemTileStyleMarshaller,
- functionalityTypeMarshaller: VerticalGridItemTopicFunctionalityTypeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(verticalGridItemTopicTile: VerticalGridItemTopicTile): urt.VerticalGridItemContent =
- urt.VerticalGridItemContent.TopicTile(
- urt.VerticalGridItemTopicTile(
- topicId = verticalGridItemTopicTile.id.toString,
- style = verticalGridItemTopicTile.style
- .map(styleMarshaller(_)).getOrElse(urt.VerticalGridItemTileStyle.SingleStateDefault),
- functionalityType = verticalGridItemTopicTile.functionalityType
- .map(functionalityTypeMarshaller(_)).getOrElse(
- urt.VerticalGridItemTopicFunctionalityType.Pivot),
- url = verticalGridItemTopicTile.url.map(urlMarshaller(_))
- )
- )
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala
deleted file mode 100644
index 816327cc6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.AspectRatio
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class AspectRatioMarshaller @Inject() () {
-
- def apply(aspectRatio: AspectRatio): urt.AspectRatio = urt.AspectRatio(
- numerator = aspectRatio.numerator,
- denominator = aspectRatio.denominator
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD
deleted file mode 100644
index 76deb3159..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala
deleted file mode 100644
index c1abb20f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.BroadcastId
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class BroadcastIdMarshaller @Inject() () {
-
- def apply(broadcastId: BroadcastId): urt.BroadcastId = urt.BroadcastId(
- id = broadcastId.id
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala
deleted file mode 100644
index b662e0a8b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.BroadcastId
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Image
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.MediaEntity
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.TweetMedia
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MediaEntityMarshaller @Inject() (
- tweetMediaMarshaller: TweetMediaMarshaller,
- broadcastIdMarshaller: BroadcastIdMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller) {
-
- def apply(mediaEntity: MediaEntity): urt.MediaEntity = mediaEntity match {
- case tweetMedia: TweetMedia => urt.MediaEntity.TweetMedia(tweetMediaMarshaller(tweetMedia))
- case broadcastId: BroadcastId => urt.MediaEntity.BroadcastId(broadcastIdMarshaller(broadcastId))
- case image: Image => urt.MediaEntity.Image(imageVariantMarshaller(image.image))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala
deleted file mode 100644
index 0ab4e36d5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.MediaKey
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MediaKeyMarshaller @Inject() () {
-
- def apply(mediaKey: MediaKey): urt.MediaKey = urt.MediaKey(
- id = mediaKey.id,
- category = mediaKey.category
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala
deleted file mode 100644
index 1a1f18f04..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MediaMarshaller @Inject() (
- mediaEntityMarshaller: MediaEntityMarshaller,
- mediaKeyMarshaller: MediaKeyMarshaller,
- rectMarshaller: RectMarshaller,
- aspectRatioMarshaller: AspectRatioMarshaller) {
-
- def apply(media: Media): urt.Media = urt.Media(
- mediaEntity = media.mediaEntity.map(mediaEntityMarshaller(_)),
- mediaKey = media.mediaKey.map(mediaKeyMarshaller(_)),
- imagePossibleCropping = media.imagePossibleCropping.map { rects =>
- rects.map(rectMarshaller(_))
- },
- aspectRatio = media.aspectRatio.map(aspectRatioMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala
deleted file mode 100644
index 155243393..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Rect
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class RectMarshaller @Inject() () {
-
- def apply(rect: Rect): urt.Rect = urt.Rect(
- left = rect.left,
- top = rect.top,
- width = rect.width,
- height = rect.height
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala
deleted file mode 100644
index 0c4183c73..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.TweetMedia
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TweetMediaMarshaller @Inject() () {
-
- def apply(tweetMedia: TweetMedia): urt.TweetMedia = urt.TweetMedia(
- tweetId = tweetMedia.tweetId,
- momentId = tweetMedia.momentId
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala
deleted file mode 100644
index d5e356ad9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ArticleDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ArticleDetailsMarshaller @Inject() () {
-
- def apply(articleDetails: ArticleDetails): urt.ArticleDetails = urt.ArticleDetails(
- articlePosition = articleDetails.articlePosition,
- shareCount = articleDetails.shareCount
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD
deleted file mode 100644
index e516fc9b4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala
deleted file mode 100644
index 569cd6a81..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class BadgeMarshaller @Inject() (
- rosettaColorMarshaller: RosettaColorMarshaller) {
-
- def apply(badge: Badge): urt.Badge = urt.Badge(
- text = badge.text,
- textColorName = badge.textColorName.map(rosettaColorMarshaller(_)),
- backgroundColorName = badge.backgroundColorName.map(rosettaColorMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala
deleted file mode 100644
index f1cbddfe5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CallbackMarshaller @Inject() () {
-
- def apply(callback: Callback): urt.Callback = urt.Callback(
- endpoint = callback.endpoint
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala
deleted file mode 100644
index 6a3df4dbc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ChildFeedbackAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ChildFeedbackActionMarshaller @Inject() (
- feedbackTypeMarshaller: FeedbackTypeMarshaller,
- confirmationDisplayTypeMarshaller: ConfirmationDisplayTypeMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- horizonIconMarshaller: HorizonIconMarshaller,
- richFeedbackBehaviorMarshaller: RichFeedbackBehaviorMarshaller) {
-
- def apply(feedbackAction: ChildFeedbackAction): urt.FeedbackAction = {
- urt.FeedbackAction(
- feedbackType = feedbackTypeMarshaller(feedbackAction.feedbackType),
- prompt = feedbackAction.prompt,
- confirmation = feedbackAction.confirmation,
- childKeys = None,
- feedbackUrl = feedbackAction.feedbackUrl,
- hasUndoAction = feedbackAction.hasUndoAction,
- confirmationDisplayType =
- feedbackAction.confirmationDisplayType.map(confirmationDisplayTypeMarshaller(_)),
- clientEventInfo = feedbackAction.clientEventInfo.map(clientEventInfoMarshaller(_)),
- icon = feedbackAction.icon.map(horizonIconMarshaller(_)),
- richBehavior = feedbackAction.richBehavior.map(richFeedbackBehaviorMarshaller(_)),
- subprompt = feedbackAction.subprompt
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala
deleted file mode 100644
index 6d24a048a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ClientEventDetailsMarshaller @Inject() (
- conversationDetailsMarshaller: ConversationDetailsMarshaller,
- timelinesDetailsMarshaller: TimelinesDetailsMarshaller,
- articleDetailsMarshaller: ArticleDetailsMarshaller,
- liveEventDetailsMarshaller: LiveEventDetailsMarshaller,
- commerceDetailsMarshaller: CommerceDetailsMarshaller) {
-
- def apply(clientEventDetails: ClientEventDetails): urt.ClientEventDetails = {
- urt.ClientEventDetails(
- conversationDetails =
- clientEventDetails.conversationDetails.map(conversationDetailsMarshaller(_)),
- timelinesDetails = clientEventDetails.timelinesDetails.map(timelinesDetailsMarshaller(_)),
- articleDetails = clientEventDetails.articleDetails.map(articleDetailsMarshaller(_)),
- liveEventDetails = clientEventDetails.liveEventDetails.map(liveEventDetailsMarshaller(_)),
- commerceDetails = clientEventDetails.commerceDetails.map(commerceDetailsMarshaller(_))
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala
deleted file mode 100644
index aff10b9ed..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ClientEventInfoMarshaller @Inject() (
- clientEventDetailsMarshaller: ClientEventDetailsMarshaller) {
-
- def apply(clientEventInfo: ClientEventInfo): urt.ClientEventInfo = {
- urt.ClientEventInfo(
- component = clientEventInfo.component,
- element = clientEventInfo.element,
- details = clientEventInfo.details.map(clientEventDetailsMarshaller(_)),
- action = clientEventInfo.action,
- entityToken = clientEventInfo.entityToken
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala
deleted file mode 100644
index 3b14c7a05..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.CommerceDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CommerceDetailsMarshaller @Inject() () {
-
- def apply(commerceDetails: CommerceDetails): urt.CommerceDetails = urt.CommerceDetails(
- dropId = commerceDetails.dropId,
- shopV2Id = commerceDetails.shopV2Id,
- productKey = commerceDetails.productKey,
- merchantId = commerceDetails.merchantId,
- productIndex = commerceDetails.productIndex,
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala
deleted file mode 100644
index 78a74254f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BottomSheet
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConfirmationDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Inline
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConfirmationDisplayTypeMarshaller @Inject() () {
-
- def apply(confirmationDisplayType: ConfirmationDisplayType): urt.ConfirmationDisplayType =
- confirmationDisplayType match {
- case Inline => urt.ConfirmationDisplayType.Inline
- case BottomSheet => urt.ConfirmationDisplayType.BottomSheet
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala
deleted file mode 100644
index 88889bb5f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConversationDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConversationDetailsMarshaller @Inject() (sectionMarshaller: ConversationSectionMarshaller) {
-
- def apply(conversationDetails: ConversationDetails): urt.ConversationDetails =
- urt.ConversationDetails(
- conversationSection = conversationDetails.conversationSection.map(sectionMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala
deleted file mode 100644
index 0ae3e5bf0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.AbusiveQuality
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConversationSection
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HighQuality
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LowQuality
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RelatedTweet
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ConversationSectionMarshaller @Inject() () {
-
- def apply(section: ConversationSection): urt.ConversationSection = section match {
- case HighQuality => urt.ConversationSection.HighQuality
- case LowQuality => urt.ConversationSection.LowQuality
- case AbusiveQuality => urt.ConversationSection.AbusiveQuality
- case RelatedTweet => urt.ConversationSection.RelatedTweet
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala
deleted file mode 100644
index 61bcdec68..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class DismissInfoMarshaller @Inject() (callbackMarshaller: CallbackMarshaller) {
-
- def apply(dismissInfo: DismissInfo): urt.DismissInfo =
- urt.DismissInfo(dismissInfo.callbacks.map(_.map(callbackMarshaller(_))))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala
deleted file mode 100644
index 5be361b30..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackActionMarshaller.generateKey
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-object FeedbackActionMarshaller {
- def generateKey(feedbackAction: urt.FeedbackAction): String = {
- feedbackAction.hashCode.toString
- }
-}
-
-@Singleton
-class FeedbackActionMarshaller @Inject() (
- childFeedbackActionMarshaller: ChildFeedbackActionMarshaller,
- feedbackTypeMarshaller: FeedbackTypeMarshaller,
- confirmationDisplayTypeMarshaller: ConfirmationDisplayTypeMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller,
- horizonIconMarshaller: HorizonIconMarshaller,
- richFeedbackBehaviorMarshaller: RichFeedbackBehaviorMarshaller) {
-
- def apply(feedbackAction: FeedbackAction): urt.FeedbackAction = {
- val childKeys = feedbackAction.childFeedbackActions
- .map(_.map { childFeedbackAction =>
- val urtChildFeedbackAction = childFeedbackActionMarshaller(childFeedbackAction)
- generateKey(urtChildFeedbackAction)
- })
-
- urt.FeedbackAction(
- feedbackType = feedbackTypeMarshaller(feedbackAction.feedbackType),
- prompt = feedbackAction.prompt,
- confirmation = feedbackAction.confirmation,
- childKeys = childKeys,
- feedbackUrl = feedbackAction.feedbackUrl,
- hasUndoAction = feedbackAction.hasUndoAction,
- confirmationDisplayType =
- feedbackAction.confirmationDisplayType.map(confirmationDisplayTypeMarshaller(_)),
- clientEventInfo = feedbackAction.clientEventInfo.map(clientEventInfoMarshaller(_)),
- icon = feedbackAction.icon.map(horizonIconMarshaller(_)),
- richBehavior = feedbackAction.richBehavior.map(richFeedbackBehaviorMarshaller(_)),
- subprompt = feedbackAction.subprompt,
- encodedFeedbackRequest = feedbackAction.encodedFeedbackRequest
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala
deleted file mode 100644
index 068450e02..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackDisplayContext
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FeedbackDisplayContextMarshaller @Inject() () {
-
- def apply(displayContext: FeedbackDisplayContext): urt.FeedbackDisplayContext =
- urt.FeedbackDisplayContext(
- reason = displayContext.reason
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala
deleted file mode 100644
index 5f8b4b988..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FeedbackInfoMarshaller @Inject() (
- feedbackActionMarshaller: FeedbackActionMarshaller,
- feedbackDisplayContextMarshaller: FeedbackDisplayContextMarshaller,
- clientEventInfoMarshaller: ClientEventInfoMarshaller) {
-
- def apply(feedbackActionInfo: FeedbackActionInfo): urt.FeedbackInfo = urt.FeedbackInfo(
- // Generate key from the hashcode of the marshalled feedback action URT
- feedbackKeys = feedbackActionInfo.feedbackActions
- .map(feedbackActionMarshaller(_)).map(FeedbackActionMarshaller.generateKey),
- feedbackMetadata = feedbackActionInfo.feedbackMetadata,
- displayContext = feedbackActionInfo.displayContext.map(feedbackDisplayContextMarshaller(_)),
- clientEventInfo = feedbackActionInfo.clientEventInfo.map(clientEventInfoMarshaller(_)),
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala
deleted file mode 100644
index 6b76c31e0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class FeedbackTypeMarshaller @Inject() () {
-
- def apply(feedbackType: FeedbackType): urt.FeedbackType = feedbackType match {
- case Dismiss => urt.FeedbackType.Dismiss
- case SeeFewer => urt.FeedbackType.SeeFewer
- case DontLike => urt.FeedbackType.DontLike
- case NotRelevant => urt.FeedbackType.NotRelevant
- case SeeMore => urt.FeedbackType.SeeMore
- case NotCredible => urt.FeedbackType.NotCredible
- case GiveFeedback => urt.FeedbackType.GiveFeedback
- case NotRecent => urt.FeedbackType.NotRecent
- case UnfollowEntity => urt.FeedbackType.UnfollowEntity
- case Relevant => urt.FeedbackType.Relevant
- case Moderate => urt.FeedbackType.Moderate
- case RichBehavior => urt.FeedbackType.RichBehavior
- case NotAboutTopic => urt.FeedbackType.NotAboutTopic
- case Generic => urt.FeedbackType.Generic
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala
deleted file mode 100644
index 91c2033cc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GeneralContextMarshaller @Inject() (
- generalContextTypeMarshaller: GeneralContextTypeMarshaller,
- urlMarshaller: UrlMarshaller) {
-
- def apply(generalContext: GeneralContext): urt.SocialContext = {
- urt.SocialContext.GeneralContext(
- urt.GeneralContext(
- contextType = generalContextTypeMarshaller(generalContext.contextType),
- text = generalContext.text,
- url = generalContext.url,
- contextImageUrls = generalContext.contextImageUrls,
- landingUrl = generalContext.landingUrl.map(urlMarshaller(_))
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala
deleted file mode 100644
index 982be27ab..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GeneralContextTypeMarshaller @Inject() () {
-
- def apply(generalContextType: GeneralContextType): urt.ContextType = generalContextType match {
- case LikeGeneralContextType => urt.ContextType.Like
- case FollowGeneralContextType => urt.ContextType.Follow
- case MomentGeneralContextType => urt.ContextType.Moment
- case ReplyGeneralContextType => urt.ContextType.Reply
- case ConversationGeneralContextType => urt.ContextType.Conversation
- case PinGeneralContextType => urt.ContextType.Pin
- case TextOnlyGeneralContextType => urt.ContextType.TextOnly
- case FacePileGeneralContextType => urt.ContextType.Facepile
- case MegaPhoneGeneralContextType => urt.ContextType.Megaphone
- case BirdGeneralContextType => urt.ContextType.Bird
- case FeedbackGeneralContextType => urt.ContextType.Feedback
- case TopicGeneralContextType => urt.ContextType.Topic
- case ListGeneralContextType => urt.ContextType.List
- case RetweetGeneralContextType => urt.ContextType.Retweet
- case LocationGeneralContextType => urt.ContextType.Location
- case CommunityGeneralContextType => urt.ContextType.Community
- case NewUserGeneralContextType => urt.ContextType.NewUser
- case SmartblockExpirationGeneralContextType => urt.ContextType.SmartBlockExpiration
- case TrendingGeneralContextType => urt.ContextType.Trending
- case SparkleGeneralContextType => urt.ContextType.Sparkle
- case SpacesGeneralContextType => urt.ContextType.Spaces
- case ReplyPinGeneralContextType => urt.ContextType.ReplyPin
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala
deleted file mode 100644
index 50c0c2519..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Bounce
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ImageAnimationTypeMarshaller @Inject() () {
-
- def apply(imageAnimationType: ImageAnimationType): urt.ImageAnimationType =
- imageAnimationType match {
- case Bounce => urt.ImageAnimationType.Bounce
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala
deleted file mode 100644
index 6021f26e8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Icon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FullWidth
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.IconSmall
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ImageDisplayTypeMarshaller @Inject() () {
-
- def apply(imageDisplayType: ImageDisplayType): urt.ImageDisplayType =
- imageDisplayType match {
- case Icon => urt.ImageDisplayType.Icon
- case FullWidth => urt.ImageDisplayType.FullWidth
- case IconSmall => urt.ImageDisplayType.IconSmall
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala
deleted file mode 100644
index a5711cf43..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorPaletteMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ImageVariantMarshaller @Inject() (
- colorPaletteMarshaller: ColorPaletteMarshaller) {
-
- def apply(imageVariant: ImageVariant): urt.ImageVariant = urt.ImageVariant(
- url = imageVariant.url,
- width = imageVariant.width,
- height = imageVariant.height,
- palette = imageVariant.palette.map { paletteList => paletteList.map(colorPaletteMarshaller(_)) }
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala
deleted file mode 100644
index e07d20251..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LiveEventDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class LiveEventDetailsMarshaller @Inject() () {
-
- def apply(liveEventDetails: LiveEventDetails): urt.LiveEventDetails = urt.LiveEventDetails(
- eventId = liveEventDetails.eventId
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala
deleted file mode 100644
index 43ec36fe4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.NotPinnableReplyPinState
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableReplyPinState
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnedReplyPinState
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorBlockUser
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorMarkNotInterestedTopic
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReplyPinState
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReportList
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReportTweet
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowTopic
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowTopicV2
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowUser
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleMuteList
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleMuteUser
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RichFeedbackBehaviorMarshaller @Inject() () {
-
- def apply(richFeedbackBehavior: RichFeedbackBehavior): urt.RichFeedbackBehavior =
- richFeedbackBehavior match {
- case RichFeedbackBehaviorReportList(listId, userId) =>
- urt.RichFeedbackBehavior.ReportList(urt.RichFeedbackBehaviorReportList(listId, userId))
- case RichFeedbackBehaviorBlockUser(userId) =>
- urt.RichFeedbackBehavior.BlockUser(urt.RichFeedbackBehaviorBlockUser(userId))
- case RichFeedbackBehaviorToggleFollowTopic(topicId) =>
- urt.RichFeedbackBehavior.ToggleFollowTopic(
- urt.RichFeedbackBehaviorToggleFollowTopic(topicId))
- case RichFeedbackBehaviorToggleFollowTopicV2(topicId) =>
- urt.RichFeedbackBehavior.ToggleFollowTopicV2(
- urt.RichFeedbackBehaviorToggleFollowTopicV2(topicId))
- case RichFeedbackBehaviorToggleMuteList(listId) =>
- urt.RichFeedbackBehavior.ToggleMuteList(urt.RichFeedbackBehaviorToggleMuteList(listId))
- case RichFeedbackBehaviorMarkNotInterestedTopic(topicId) =>
- urt.RichFeedbackBehavior.MarkNotInterestedTopic(
- urt.RichFeedbackBehaviorMarkNotInterestedTopic(topicId))
- case RichFeedbackBehaviorReplyPinState(replyPinState) =>
- val pinState: urt.ReplyPinState = replyPinState match {
- case PinnedReplyPinState => urt.ReplyPinState.Pinned
- case PinnableReplyPinState => urt.ReplyPinState.Pinnable
- case NotPinnableReplyPinState => urt.ReplyPinState.NotPinnable
- }
- urt.RichFeedbackBehavior.ReplyPinState(urt.RichFeedbackBehaviorReplyPinState(pinState))
- case RichFeedbackBehaviorToggleMuteUser(userId) =>
- urt.RichFeedbackBehavior.ToggleMuteUser(urt.RichFeedbackBehaviorToggleMuteUser(userId))
- case RichFeedbackBehaviorToggleFollowUser(userId) =>
- urt.RichFeedbackBehavior.ToggleFollowUser(urt.RichFeedbackBehaviorToggleFollowUser(userId))
- case RichFeedbackBehaviorReportTweet(entryId) =>
- urt.RichFeedbackBehavior.ReportTweet(urt.RichFeedbackBehaviorReportTweet(entryId))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala
deleted file mode 100644
index 7d43812ea..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.timelines.render.{thriftscala => urt}
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContext
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SocialContextMarshaller @Inject() (
- generalContextMarshaller: GeneralContextMarshaller,
- topicContextMarshaller: TopicContextMarshaller) {
-
- def apply(socialContext: SocialContext): urt.SocialContext =
- socialContext match {
- case generalContextBanner: GeneralContext =>
- generalContextMarshaller(generalContextBanner)
- case topicContextBanner: TopicContext =>
- topicContextMarshaller(topicContextBanner)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala
deleted file mode 100644
index 657f49e75..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelinesDetailsMarshaller @Inject() () {
-
- def apply(timelinesDetails: TimelinesDetails): urt.TimelinesDetails = urt.TimelinesDetails(
- injectionType = timelinesDetails.injectionType,
- controllerData = timelinesDetails.controllerData,
- sourceData = timelinesDetails.sourceData
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala
deleted file mode 100644
index e46f64614..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BasicTopicContextFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RecWithEducationTopicContextFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RecommendationTopicContextFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContextFunctionalityType
-import com.twitter.timelines.render.{thriftscala => urt}
-
-object TopicContextFunctionalityTypeMarshaller {
-
- def apply(
- topicContextFunctionalityType: TopicContextFunctionalityType
- ): urt.TopicContextFunctionalityType = topicContextFunctionalityType match {
- case BasicTopicContextFunctionalityType => urt.TopicContextFunctionalityType.Basic
- case RecommendationTopicContextFunctionalityType =>
- urt.TopicContextFunctionalityType.Recommendation
- case RecWithEducationTopicContextFunctionalityType =>
- urt.TopicContextFunctionalityType.RecWithEducation
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala
deleted file mode 100644
index 0c067e299..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BasicTopicContextFunctionalityType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContext
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TopicContextMarshaller @Inject() () {
-
- def apply(topicContext: TopicContext): urt.SocialContext = {
- urt.SocialContext.TopicContext(
- urt.TopicContext(
- topicId = topicContext.topicId,
- functionalityType = TopicContextFunctionalityTypeMarshaller(
- topicContext.functionalityType.getOrElse(BasicTopicContextFunctionalityType))
- )
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala
deleted file mode 100644
index 65c8ba30d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UrlMarshaller @Inject() (
- urlTypeMarshaller: UrlTypeMarshaller,
- urtEndpointOptionsMarshaller: UrtEndpointOptionsMarshaller) {
-
- def apply(url: Url): urt.Url = urt.Url(
- urlType = urlTypeMarshaller(url.urlType),
- url = url.url,
- urtEndpointOptions = url.urtEndpointOptions.map(urtEndpointOptionsMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala
deleted file mode 100644
index 4d2796535..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpoint
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UrlTypeMarshaller @Inject() () {
-
- def apply(urlType: UrlType): urt.UrlType = urlType match {
- case ExternalUrl => urt.UrlType.ExternalUrl
- case DeepLink => urt.UrlType.DeepLink
- case UrtEndpoint => urt.UrlType.UrtEndpoint
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala
deleted file mode 100644
index d9d5c80ce..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpointOptions
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UrtEndpointOptionsMarshaller @Inject() () {
-
- def apply(urtEndpointOptions: UrtEndpointOptions): urt.UrtEndpointOptions =
- urt.UrtEndpointOptions(
- requestParams = urtEndpointOptions.requestParams,
- title = urtEndpointOptions.title,
- cacheId = urtEndpointOptions.cacheId,
- subtitle = urtEndpointOptions.subtitle
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD
deleted file mode 100644
index 7d10b934c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala
deleted file mode 100644
index 881891183..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorDisplayTreatment
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CursorDisplayTreatmentMarshaller @Inject() () {
-
- def apply(treatment: CursorDisplayTreatment): urt.CursorDisplayTreatment =
- urt.CursorDisplayTreatment(
- actionText = treatment.actionText,
- labelText = treatment.labelText
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala
deleted file mode 100644
index 00d83fad1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CursorItemMarshaller @Inject() (
- cursorTypeMarshaller: CursorTypeMarshaller,
- cursorDisplayTreatmentMarshaller: CursorDisplayTreatmentMarshaller) {
-
- def apply(cursorItem: CursorItem): urt.TimelineItemContent.TimelineCursor =
- urt.TimelineItemContent.TimelineCursor(
- urt.TimelineCursor(
- value = cursorItem.value,
- cursorType = cursorTypeMarshaller(cursorItem.cursorType),
- displayTreatment = cursorItem.displayTreatment.map(cursorDisplayTreatmentMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala
deleted file mode 100644
index fedf19c65..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CursorOperationMarshaller @Inject() (
- cursorTypeMarshaller: CursorTypeMarshaller,
- cursorDisplayTreatmentMarshaller: CursorDisplayTreatmentMarshaller) {
-
- def apply(cursorOperation: CursorOperation): urt.TimelineOperation.Cursor =
- urt.TimelineOperation.Cursor(
- urt.TimelineCursor(
- value = cursorOperation.value,
- cursorType = cursorTypeMarshaller(cursorOperation.cursorType),
- displayTreatment = cursorOperation.displayTreatment.map(cursorDisplayTreatmentMarshaller(_))
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala
deleted file mode 100644
index 9359b069c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation._
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CursorTypeMarshaller @Inject() () {
-
- def apply(cursorType: CursorType): urt.CursorType = cursorType match {
- case TopCursor => urt.CursorType.Top
- case BottomCursor => urt.CursorType.Bottom
- case GapCursor => urt.CursorType.Gap
- case PivotCursor => urt.CursorType.Pivot
- case SubBranchCursor => urt.CursorType.Subbranch
- case ShowMoreCursor => urt.CursorType.ShowMore
- case ShowMoreThreadsCursor => urt.CursorType.ShowMoreThreads
- case ShowMoreThreadsPromptCursor => urt.CursorType.ShowMoreThreadsPrompt
- case SecondRepliesSectionCursor => urt.CursorType.SecondRepliesSection
- case ThirdRepliesSectionCursor => urt.CursorType.ThirdRepliesSection
- }
-
- def unmarshall(cursorType: urt.CursorType): CursorType = cursorType match {
- case urt.CursorType.Top => TopCursor
- case urt.CursorType.Bottom => BottomCursor
- case urt.CursorType.Gap => GapCursor
- case urt.CursorType.Pivot => PivotCursor
- case urt.CursorType.Subbranch => SubBranchCursor
- case urt.CursorType.ShowMore => ShowMoreCursor
- case urt.CursorType.ShowMoreThreads => ShowMoreThreadsCursor
- case urt.CursorType.ShowMoreThreadsPrompt => ShowMoreThreadsPromptCursor
- case urt.CursorType.SecondRepliesSection => SecondRepliesSectionCursor
- case urt.CursorType.ThirdRepliesSection => ThirdRepliesSectionCursor
- case urt.CursorType.EnumUnknownCursorType(id) =>
- throw new UnsupportedOperationException(s"Unexpected cursor enum field: $id")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala
deleted file mode 100644
index e525e3495..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.AdMetadataContainer
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdMetadataContainerMarshaller @Inject() (
- sponsorshipTypeMarshaller: SponsorshipTypeMarshaller,
- disclaimerTypeMarshaller: DisclaimerTypeMarshaller,
- skAdNetworkDataMarshaller: SkAdNetworkDataMarshaller) {
-
- def apply(adMetadataContainer: AdMetadataContainer): urt.AdMetadataContainer =
- urt.AdMetadataContainer(
- removePromotedAttributionForPreroll = adMetadataContainer.removePromotedAttributionForPreroll,
- sponsorshipCandidate = adMetadataContainer.sponsorshipCandidate,
- sponsorshipOrganization = adMetadataContainer.sponsorshipOrganization,
- sponsorshipOrganizationWebsite = adMetadataContainer.sponsorshipOrganizationWebsite,
- sponsorshipType = adMetadataContainer.sponsorshipType.map(sponsorshipTypeMarshaller(_)),
- disclaimerType = adMetadataContainer.disclaimerType.map(disclaimerTypeMarshaller(_)),
- skAdNetworkDataList =
- adMetadataContainer.skAdNetworkDataList.map(_.map(skAdNetworkDataMarshaller(_))),
- unifiedCardOverride = adMetadataContainer.unifiedCardOverride
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD
deleted file mode 100644
index 6ac0230f9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala
deleted file mode 100644
index 5c55b1a59..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.CallToAction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Singleton
-
-@Singleton
-class CallToActionMarshaller {
- def apply(callToAction: CallToAction): urt.CallToAction = {
- urt.CallToAction(
- callToActionType = callToAction.callToActionType,
- url = callToAction.url
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala
deleted file mode 100644
index c174b4107..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.ClickTrackingInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ClickTrackingInfoMarshaller @Inject() (
- urlOverrideTypeMarshaller: UrlOverrideTypeMarshaller) {
-
- def apply(clickTrackingInfo: ClickTrackingInfo): urt.ClickTrackingInfo =
- urt.ClickTrackingInfo(
- urlParams = clickTrackingInfo.urlParams,
- urlOverride = clickTrackingInfo.urlOverride,
- urlOverrideType = clickTrackingInfo.urlOverrideType.map(urlOverrideTypeMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala
deleted file mode 100644
index 764eefa04..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerIssue
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerPolitical
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class DisclaimerTypeMarshaller @Inject() () {
-
- def apply(disclaimerType: DisclaimerType): urt.DisclaimerType = disclaimerType match {
- case DisclaimerPolitical => urt.DisclaimerType.Political
- case DisclaimerIssue => urt.DisclaimerType.Issue
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala
deleted file mode 100644
index dfabdd6d9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Earned
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Issue
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoDisclosure
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Political
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class DisclosureTypeMarshaller @Inject() () {
-
- def apply(disclosureType: DisclosureType): urt.DisclosureType = disclosureType match {
- case NoDisclosure => urt.DisclosureType.NoDisclosure
- case Political => urt.DisclosureType.Political
- case Earned => urt.DisclosureType.Earned
- case Issue => urt.DisclosureType.Issue
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala
deleted file mode 100644
index f009b89a3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Amplify
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DynamicPrerollType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.LiveTvEvent
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Marketplace
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class DynamicPrerollTypeMarshaller @Inject() () {
-
- def apply(dynamicPrerollType: DynamicPrerollType): urt.DynamicPrerollType =
- dynamicPrerollType match {
- case Amplify => urt.DynamicPrerollType.Amplify
- case Marketplace => urt.DynamicPrerollType.Marketplace
- case LiveTvEvent => urt.DynamicPrerollType.LiveTvEvent
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala
deleted file mode 100644
index e9ce5b414..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.MediaInfo
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MediaInfoMarshaller @Inject() (
- callToActionMarshaller: CallToActionMarshaller,
- videoVariantsMarshaller: VideoVariantsMarshaller) {
- def apply(mediaInfo: MediaInfo): urt.MediaInfo = {
- urt.MediaInfo(
- uuid = mediaInfo.uuid,
- publisherId = mediaInfo.publisherId,
- callToAction = mediaInfo.callToAction.map(callToActionMarshaller(_)),
- durationMillis = mediaInfo.durationMillis,
- videoVariants = mediaInfo.videoVariants.map(videoVariantsMarshaller(_)),
- advertiserName = mediaInfo.advertiserName,
- renderAdByAdvertiserName = mediaInfo.renderAdByAdvertiserName,
- advertiserProfileImageUrl = mediaInfo.advertiserProfileImageUrl
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala
deleted file mode 100644
index 184540489..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Preroll
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PrerollMarshaller @Inject() (
- dynamicPrerollTypeMarshaller: DynamicPrerollTypeMarshaller,
- mediaInfoMarshaller: MediaInfoMarshaller) {
-
- def apply(preroll: Preroll): urt.Preroll =
- urt.Preroll(
- prerollId = preroll.prerollId,
- dynamicPrerollType = preroll.dynamicPrerollType.map(dynamicPrerollTypeMarshaller(_)),
- mediaInfo = preroll.mediaInfo.map(mediaInfoMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala
deleted file mode 100644
index 65197a8cd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PrerollMetadataMarshaller @Inject() (
- prerollMarshaller: PrerollMarshaller) {
- def apply(prerollMetadata: PrerollMetadata): urt.PrerollMetadata =
- urt.PrerollMetadata(
- preroll = prerollMetadata.preroll.map(prerollMarshaller(_)),
- videoAnalyticsScribePassthrough = prerollMetadata.videoAnalyticsScribePassthrough
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala
deleted file mode 100644
index 6a1e1750e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PromotedMetadataMarshaller @Inject() (
- disclosureTypeMarshaller: DisclosureTypeMarshaller,
- adMetadataContainerMarshaller: AdMetadataContainerMarshaller,
- clickTrackingInfoMarshaller: ClickTrackingInfoMarshaller) {
-
- /** See comments on [[com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata]]
- * regarding impressionId and impressionString
- *
- * TL;DR the domain model only has impressionString (the newer version) an this marshaller sets both
- * impressionId (the older) and impressionString based on it for compatibility.
- * */
- def apply(promotedMetadata: PromotedMetadata): urt.PromotedMetadata =
- urt.PromotedMetadata(
- advertiserId = promotedMetadata.advertiserId,
- impressionId = promotedMetadata.impressionString,
- disclosureType = promotedMetadata.disclosureType.map(disclosureTypeMarshaller(_)),
- experimentValues = promotedMetadata.experimentValues,
- promotedTrendId = promotedMetadata.promotedTrendId,
- promotedTrendName = promotedMetadata.promotedTrendName,
- promotedTrendQueryTerm = promotedMetadata.promotedTrendQueryTerm,
- adMetadataContainer =
- promotedMetadata.adMetadataContainer.map(adMetadataContainerMarshaller(_)),
- promotedTrendDescription = promotedMetadata.promotedTrendDescription,
- impressionString = promotedMetadata.impressionString,
- clickTrackingInfo = promotedMetadata.clickTrackingInfo.map(clickTrackingInfoMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala
deleted file mode 100644
index cd1813508..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SkAdNetworkData
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class SkAdNetworkDataMarshaller @Inject() () {
-
- def apply(skAdNetworkData: SkAdNetworkData): urt.SkAdNetworkData =
- urt.SkAdNetworkData(
- version = skAdNetworkData.version,
- srcAppId = skAdNetworkData.srcAppId,
- dstAppId = skAdNetworkData.dstAppId,
- adNetworkId = skAdNetworkData.adNetworkId,
- campaignId = skAdNetworkData.campaignId,
- impressionTimeInMillis = skAdNetworkData.impressionTimeInMillis,
- nonce = skAdNetworkData.nonce,
- signature = skAdNetworkData.signature,
- fidelityType = skAdNetworkData.fidelityType
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala
deleted file mode 100644
index 7c892eef1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DirectSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.IndirectSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoSponsorshipSponsorshipType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SponsorshipType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class SponsorshipTypeMarshaller @Inject() () {
-
- def apply(sponsorshipType: SponsorshipType): urt.SponsorshipType = sponsorshipType match {
- case DirectSponsorshipType => urt.SponsorshipType.Direct
- case IndirectSponsorshipType => urt.SponsorshipType.Indirect
- case NoSponsorshipSponsorshipType => urt.SponsorshipType.NoSponsorship
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala
deleted file mode 100644
index ea76457c1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DcmUrlOverrideType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UnknownUrlOverrideType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UrlOverrideType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class UrlOverrideTypeMarshaller @Inject() () {
-
- def apply(urlOverrideType: UrlOverrideType): urt.UrlOverrideType = urlOverrideType match {
- case UnknownUrlOverrideType => urt.UrlOverrideType.Unknown
- case DcmUrlOverrideType => urt.UrlOverrideType.Dcm
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala
deleted file mode 100644
index d3ab9188d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.VideoVariant
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Singleton
-
-@Singleton
-class VideoVariantsMarshaller {
- def apply(videoVariants: Seq[VideoVariant]): Seq[urt.VideoVariant] = {
- videoVariants.map(videoVariant =>
- urt.VideoVariant(
- url = videoVariant.url,
- contentType = videoVariant.contentType,
- bitrate = videoVariant.bitrate
- ))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD
deleted file mode 100644
index 527e20c0c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala
deleted file mode 100644
index 56a2d53ad..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.ImmediateTimelineReaction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.RemoteTimelineReaction
-import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.TimelineReaction
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TimelineReactionMarshaller @Inject() () {
- def apply(timelineReaction: TimelineReaction): urt.TimelineReaction = {
- val execution = timelineReaction.execution match {
- case ImmediateTimelineReaction(key) =>
- urt.TimelineReactionExecution.Immediate(urt.ImmediateTimelineReaction(key))
- case RemoteTimelineReaction(requestParams, timeoutInSeconds) =>
- urt.TimelineReactionExecution.Remote(
- urt.RemoteTimelineReaction(
- requestParams,
- timeoutInSeconds
- ))
- }
- urt.TimelineReaction(
- execution = execution,
- maxExecutionCount = timelineReaction.maxExecutionCount
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD
deleted file mode 100644
index cdc73d8c4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala
deleted file mode 100644
index 217b9d9d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextList
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextMention
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextUser
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ReferenceObjectMarshaller @Inject() (urlMarshaller: UrlMarshaller) {
-
- def apply(ref: ReferenceObject): urt.ReferenceObject = ref match {
- case url: Url => urt.ReferenceObject.Url(urlMarshaller(url))
- case user: RichTextUser => urt.ReferenceObject.User(urt.RichTextUser(id = user.id))
- case mention: RichTextMention =>
- urt.ReferenceObject.Mention(
- urt.RichTextMention(id = mention.id, screenName = mention.screenName))
- case hashtag: RichTextHashtag =>
- urt.ReferenceObject.Hashtag(urt.RichTextHashtag(text = hashtag.text))
- case cashtag: RichTextCashtag =>
- urt.ReferenceObject.Cashtag(urt.RichTextCashtag(text = cashtag.text))
- case twitterList: RichTextList =>
- urt.ReferenceObject.TwitterList(urt.RichTextList(id = twitterList.id, url = twitterList.url))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala
deleted file mode 100644
index 24bbf07af..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Center
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Natural
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RichTextAlignmentMarshaller @Inject() () {
-
- def apply(alignment: RichTextAlignment): urt.RichTextAlignment = alignment match {
- case Natural => urt.RichTextAlignment.Natural
- case Center => urt.RichTextAlignment.Center
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala
deleted file mode 100644
index a2c7d2a6d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RichTextEntityMarshaller @Inject() (
- referenceObjectMarshaller: ReferenceObjectMarshaller,
- richTextFormatMarshaller: RichTextFormatMarshaller) {
-
- def apply(entity: RichTextEntity): urt.RichTextEntity = urt.RichTextEntity(
- fromIndex = entity.fromIndex,
- toIndex = entity.toIndex,
- ref = entity.ref.map(referenceObjectMarshaller(_)),
- format = entity.format.map(richTextFormatMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala
deleted file mode 100644
index cd24a4013..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RichTextFormatMarshaller @Inject() () {
-
- def apply(format: RichTextFormat): urt.RichTextFormat = format match {
- case Plain => urt.RichTextFormat.Plain
- case Strong => urt.RichTextFormat.Strong
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala
deleted file mode 100644
index a86b90fd4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RichTextMarshaller @Inject() (
- richTextEntityMarshaller: RichTextEntityMarshaller,
- richTextAlignmentMarshaller: RichTextAlignmentMarshaller) {
-
- def apply(richText: RichText): urt.RichText = urt.RichText(
- text = richText.text,
- entities = richText.entities.map(richTextEntityMarshaller(_)),
- rtl = richText.rtl,
- alignment = richText.alignment.map(richTextAlignmentMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala
deleted file mode 100644
index 9dda91373..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.AdsMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AdsMetadataMarshaller @Inject() () {
-
- def apply(adsMetadata: AdsMetadata): urt.AdsMetadata =
- urt.AdsMetadata(carouselId = adsMetadata.carouselId)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD
deleted file mode 100644
index 04000837b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "src/thrift/com/twitter/timelines/render:thrift-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala
deleted file mode 100644
index d86cb0462..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarouselMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class GridCarouselMetadataMarshaller @Inject() () {
-
- def apply(gridCarouselMetadata: GridCarouselMetadata): urt.GridCarouselMetadata =
- urt.GridCarouselMetadata(numRows = gridCarouselMetadata.numRows)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala
deleted file mode 100644
index b816f91e8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleConversationMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleConversationMetadataMarshaller @Inject() (
- socialContextMarshaller: SocialContextMarshaller) {
-
- def apply(
- moduleConversationMetadata: ModuleConversationMetadata
- ): urt.ModuleConversationMetadata = urt.ModuleConversationMetadata(
- allTweetIds = moduleConversationMetadata.allTweetIds,
- socialContext = moduleConversationMetadata.socialContext.map(socialContextMarshaller(_)),
- enableDeduplication = moduleConversationMetadata.enableDeduplication
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala
deleted file mode 100644
index e2ce757f4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.CompactCarousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ConversationTree
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarousel
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Vertical
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalWithContextLine
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalGrid
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class ModuleDisplayTypeMarshaller @Inject() () {
-
- def apply(displayType: ModuleDisplayType): urt.ModuleDisplayType = displayType match {
- case Vertical => urt.ModuleDisplayType.Vertical
- case Carousel => urt.ModuleDisplayType.Carousel
- case VerticalWithContextLine => urt.ModuleDisplayType.VerticalWithContextLine
- case VerticalConversation => urt.ModuleDisplayType.VerticalConversation
- case ConversationTree => urt.ModuleDisplayType.ConversationTree
- case GridCarousel => urt.ModuleDisplayType.GridCarousel
- case CompactCarousel => urt.ModuleDisplayType.CompactCarousel
- case VerticalGrid => urt.ModuleDisplayType.VerticalGrid
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala
deleted file mode 100644
index d7d485fd9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter
-import javax.inject.Inject
-import javax.inject.Singleton
-import com.twitter.timelines.render.{thriftscala => urt}
-
-@Singleton
-class ModuleFooterMarshaller @Inject() (urlMarshaller: UrlMarshaller) {
-
- def apply(footer: ModuleFooter): urt.ModuleFooter = urt.ModuleFooter(
- text = footer.text,
- landingUrl = footer.landingUrl.map(urlMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala
deleted file mode 100644
index 32cc5dc32..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ClassicNoDivider
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ContextEmphasis
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleHeaderDisplayTypeMarshaller @Inject() () {
-
- def apply(displayType: ModuleHeaderDisplayType): urt.ModuleHeaderDisplayType =
- displayType match {
- case Classic => urt.ModuleHeaderDisplayType.Classic
- case ContextEmphasis => urt.ModuleHeaderDisplayType.ContextEmphasis
- case ClassicNoDivider => urt.ModuleHeaderDisplayType.ClassicNoDivider
- }
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala
deleted file mode 100644
index 05ab3a13a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleHeaderMarshaller @Inject() (
- horizonIconMarshaller: HorizonIconMarshaller,
- imageVariantMarshaller: ImageVariantMarshaller,
- socialContextMarshaller: SocialContextMarshaller,
- moduleHeaderDisplayTypeMarshaller: ModuleHeaderDisplayTypeMarshaller) {
-
- def apply(header: ModuleHeader): urt.ModuleHeader = urt.ModuleHeader(
- text = header.text,
- sticky = header.sticky,
- icon = header.icon.map(horizonIconMarshaller(_)),
- customIcon = header.customIcon.map(imageVariantMarshaller(_)),
- socialContext = header.socialContext.map(socialContextMarshaller(_)),
- displayType = moduleHeaderDisplayTypeMarshaller(header.moduleHeaderDisplayType)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala
deleted file mode 100644
index 8c6154186..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleMetadataMarshaller @Inject() (
- adsMetadataMarshaller: AdsMetadataMarshaller,
- moduleConversationMetadataMarshaller: ModuleConversationMetadataMarshaller,
- gridCarouselMetadataMarshaller: GridCarouselMetadataMarshaller) {
-
- def apply(moduleMetadata: ModuleMetadata): urt.ModuleMetadata = urt.ModuleMetadata(
- adsMetadata = moduleMetadata.adsMetadata.map(adsMetadataMarshaller(_)),
- conversationMetadata =
- moduleMetadata.conversationMetadata.map(moduleConversationMetadataMarshaller(_)),
- gridCarouselMetadata =
- moduleMetadata.gridCarouselMetadata.map(gridCarouselMetadataMarshaller(_))
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala
deleted file mode 100644
index f0df20b3b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleShowMoreBehaviorMarshaller @Inject() (
- moduleShowMoreBehaviorRevealByCountMarshaller: ModuleShowMoreBehaviorRevealByCountMarshaller) {
-
- def apply(
- moduleShowMoreBehavior: ModuleShowMoreBehavior
- ): urt.ModuleShowMoreBehavior = moduleShowMoreBehavior match {
- case moduleShowMoreBehaviorRevealByCount: ModuleShowMoreBehaviorRevealByCount =>
- moduleShowMoreBehaviorRevealByCountMarshaller(moduleShowMoreBehaviorRevealByCount)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala
deleted file mode 100644
index 1d36e979e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount
-import com.twitter.timelines.render.{thriftscala => urt}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ModuleShowMoreBehaviorRevealByCountMarshaller @Inject() () {
-
- def apply(
- moduleShowMoreBehaviorRevealByCount: ModuleShowMoreBehaviorRevealByCount
- ): urt.ModuleShowMoreBehavior =
- urt.ModuleShowMoreBehavior.RevealByCount(
- urt.ModuleShowMoreBehaviorRevealByCount(
- initialItemsCount = moduleShowMoreBehaviorRevealByCount.initialItemsCount,
- showMoreItemsCount = moduleShowMoreBehaviorRevealByCount.showMoreItemsCount
- )
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD
deleted file mode 100644
index a5bd6af7e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala
deleted file mode 100644
index ea027f086..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.premarshaller
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation
-import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * Transforms the `selections` into a [[DomainResponseType]] object (often URT, Slice, etc)
- *
- * [[DomainMarshaller]]s may contain business logic
- *
- * @note This is different from `com.twitter.product_mixer.core.marshaller`s
- * which transforms into a wire-compatible type
- */
-trait DomainMarshaller[-Query <: PipelineQuery, DomainResponseType] extends Component {
-
- override val identifier: DomainMarshallerIdentifier
-
- /** Transforms the `selections` into a [[DomainResponseType]] object */
- def apply(
- query: Query,
- selections: Seq[CandidateWithDetails]
- ): DomainResponseType
-}
-
-class UnsupportedCandidateDomainMarshallerException(
- candidate: Any,
- candidateSource: ComponentIdentifier)
- extends UnsupportedOperationException(
- s"Domain marshaller does not support candidate ${TransportMarshaller.getSimpleName(
- candidate.getClass)} from source $candidateSource")
-
-class UndecoratedCandidateDomainMarshallerException(
- candidate: Any,
- candidateSource: ComponentIdentifier)
- extends UnsupportedOperationException(
- s"Domain marshaller does not support undecorated candidate ${TransportMarshaller
- .getSimpleName(candidate.getClass)} from source $candidateSource")
-
-class UnsupportedPresentationDomainMarshallerException(
- candidate: Any,
- presentation: UniversalPresentation,
- candidateSource: ComponentIdentifier)
- extends UnsupportedOperationException(
- s"Domain marshaller does not support decorator presentation ${TransportMarshaller
- .getSimpleName(presentation.getClass)} for candidate ${TransportMarshaller.getSimpleName(
- candidate.getClass)} from source $candidateSource")
-
-class UnsupportedModuleDomainMarshallerException(
- presentation: Option[ModulePresentation],
- candidateSource: ComponentIdentifier)
- extends UnsupportedOperationException(
- s"Domain marshaller does not support module presentation ${presentation
- .map(p =>
- TransportMarshaller
- .getSimpleName(presentation.getClass)).getOrElse("")} but was given a module from source $candidateSource")
-
-class UndecoratedModuleDomainMarshallerException(
- candidateSource: ComponentIdentifier)
- extends UnsupportedOperationException(
- s"Domain marshaller does not support undecorated module from source $candidateSource")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD
deleted file mode 100644
index 994d481fd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala
deleted file mode 100644
index 7d856c50f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.scorer
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-/** A [[Candidate]] and it's [[FeatureMap]] after being processed by a [[Scorer]] */
-case class ScoredCandidateResult[Candidate <: UniversalNoun[Any]](
- candidate: Candidate,
- scorerResult: FeatureMap)
- extends CandidateWithFeatures[Candidate] {
- override val features: FeatureMap = scorerResult
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala
deleted file mode 100644
index e224cbc48..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.scorer
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.SupportsConditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-
-/** Scores the provided `candidates` */
-trait Scorer[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]
- extends BaseBulkCandidateFeatureHydrator[Query, Candidate, Feature[_, _]]
- with SupportsConditionally[Query] {
-
- /** @see [[ScorerIdentifier]] */
- override val identifier: ScorerIdentifier
-
- /**
- * Features returned by the Scorer
- */
- def features: Set[Feature[_, _]]
-
- /**
- * Scores the provided `candidates`
- *
- * @note the returned Seq of [[FeatureMap]] must contain all the input 'candidates'
- * and be in the same order as the input 'candidates'
- **/
- def apply(
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]]
- ): Stitch[Seq[FeatureMap]]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD
deleted file mode 100644
index b1fadc1f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala
deleted file mode 100644
index aaae604dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.selector
-
-import com.twitter.product_mixer.core.functional_component.common.CandidateScope
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/** Selects some `remainingCandidates` and add them to the `result` */
-trait Selector[-Query <: PipelineQuery] {
-
- /**
- * Specifies which [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]]s
- * this [[Selector]] will apply to.
- *
- * @note it is up to each [[Selector]] implementation to correctly handle this behavior
- */
- def pipelineScope: CandidateScope
-
- /** Selects some `remainingCandidates` and add them to the `result` */
- def apply(
- query: Query,
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails]
- ): SelectorResult
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala
deleted file mode 100644
index e20a8cd6e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.selector
-
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-/**
- * The result of a [[Selector]] where items that were added
- * to the [[result]] are removed from the [[remainingCandidates]]
- */
-case class SelectorResult(
- remainingCandidates: Seq[CandidateWithDetails],
- result: Seq[CandidateWithDetails])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD
deleted file mode 100644
index 95ff9136a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala
deleted file mode 100644
index 924aa89b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.side_effect
-
-/**
- * A modifier for any [[SideEffect]] so that the request waits for it to complete before being returned
- *
- * @note this will make the [[SideEffect]]'s latency impact the overall request's latency
- *
- * @example {{{
- * class MySideEffect extends PipelineResultSideEffect[T] with ExecuteSynchronously {...}
- * }}}
- *
- * @example {{{
- * class MySideEffect extends ScribeLogEventSideEffect[T] with ExecuteSynchronously {...}
- * }}}
- */
-trait ExecuteSynchronously { _: SideEffect[_] => }
-
-/**
- * A modifier for any [[ExecuteSynchronously]] [[SideEffect]] that makes it so failures will be
- * reported in the results but wont cause the request as a whole to fail.
- */
-trait FailOpen { _: ExecuteSynchronously => }
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala
deleted file mode 100644
index d0e66a05f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.side_effect
-
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect.Inputs
-import com.twitter.product_mixer.core.model.common
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-/**
- * A side-effect that can be run with a pipeline result before transport marshalling
- *
- * @see SideEffect
- *
- * @tparam Query pipeline query
- * @tparam ResultType response after domain marshalling
- */
-trait PipelineResultSideEffect[-Query <: PipelineQuery, -ResultType <: HasMarshalling]
- extends SideEffect[Inputs[Query, ResultType]]
- with PipelineResultSideEffect.SupportsConditionally[Query, ResultType]
-
-object PipelineResultSideEffect {
-
- /**
- * Mixin for when you want to conditionally run a [[PipelineResultSideEffect]]
- *
- * This is a thin wrapper around [[common.Conditionally]] exposing a nicer API for the [[PipelineResultSideEffect]] specific use-case.
- */
- trait Conditionally[-Query <: PipelineQuery, -ResultType <: HasMarshalling]
- extends common.Conditionally[Inputs[Query, ResultType]] {
- _: PipelineResultSideEffect[Query, ResultType] =>
-
- /** @see [[common.Conditionally.onlyIf]] */
- def onlyIf(
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResultType
- ): Boolean
-
- override final def onlyIf(input: Inputs[Query, ResultType]): Boolean =
- onlyIf(
- input.query,
- input.selectedCandidates,
- input.remainingCandidates,
- input.droppedCandidates,
- input.response)
-
- }
-
- type SupportsConditionally[-Query <: PipelineQuery, -ResultType <: HasMarshalling] =
- common.SupportsConditionally[Inputs[Query, ResultType]]
-
- case class Inputs[+Query <: PipelineQuery, +ResultType <: HasMarshalling](
- query: Query,
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- response: ResultType)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala
deleted file mode 100644
index b8a4d5a2b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.side_effect
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier
-import com.twitter.stitch.Stitch
-
-/**
- * A side-effect is a ancillary action that doesn't affect the result of execution directly.
- *
- * For example: Logging, history stores
- *
- * Implementing components can express failures by throwing an exception. These exceptions
- * will be caught and not affect the request processing.
- *
- * @note Side effects execute asynchronously in a fire-and-forget way, it's important to add alerts
- * to the [[SideEffect]] component itself since a failures wont show up in metrics
- * that just monitor your pipeline as a whole.
- *
- * @see [[ExecuteSynchronously]] for modifying a [[SideEffect]] to execute with synchronously with
- * the request waiting on the side effect to complete, this will impact the overall request's latency
- **/
-trait SideEffect[-Inputs] extends Component {
-
- /** @see [[SideEffectIdentifier]] */
- override val identifier: SideEffectIdentifier
-
- def apply(inputs: Inputs): Stitch[Unit]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD
deleted file mode 100644
index 52cd7bd26..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala
deleted file mode 100644
index 454970f78..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.transformer
-
-/**
- * Populates a [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]] with Features
- * that are available in the [[CandidateSourceResult]]
- */
-trait CandidateFeatureTransformer[-CandidateSourceResult]
- extends FeatureTransformer[CandidateSourceResult]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala
deleted file mode 100644
index 58c4a8735..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.transformer
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-
-/**
- * A transformer for transforming a mixer or recommendation pipeline's query type into a candidate
- * pipeline's query type.
- * @tparam Query The parent pipeline's query type
- * @tparam CandidateSourceQuery The Candidate Source's query type that the Query should be converted to
- */
-protected[core] sealed trait BaseCandidatePipelineQueryTransformer[
- -Query <: PipelineQuery,
- +CandidateSourceQuery]
- extends Transformer[Query, CandidateSourceQuery] {
-
- override val identifier: TransformerIdentifier =
- BaseCandidatePipelineQueryTransformer.DefaultTransformerId
-}
-
-trait CandidatePipelineQueryTransformer[-Query <: PipelineQuery, CandidateSourceQuery]
- extends BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery]
-
-trait DependentCandidatePipelineQueryTransformer[-Query <: PipelineQuery, CandidateSourceQuery]
- extends BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] {
- def transform(query: Query, candidates: Seq[CandidateWithDetails]): CandidateSourceQuery
-
- final override def transform(query: Query): CandidateSourceQuery = {
- val candidates = query.features
- .map(_.get(CandidatePipelineResults)).getOrElse(
- throw PipelineFailure(
- IllegalStateFailure,
- "Candidate Pipeline Results Feature missing from query features"))
- transform(query, candidates)
- }
-}
-
-object BaseCandidatePipelineQueryTransformer {
- private[core] val DefaultTransformerId: TransformerIdentifier =
- TransformerIdentifier(ComponentIdentifier.BasedOnParentComponent)
- private[core] val TransformerIdSuffix = "Query"
-
- /**
- * For use when building a [[BaseCandidatePipelineQueryTransformer]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]]
- * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]]
- */
- private[core] def copyWithUpdatedIdentifier[Query <: PipelineQuery, CandidateSourceQuery](
- queryTransformer: BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery],
- parentIdentifier: ComponentIdentifier
- ): BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] = {
- if (queryTransformer.identifier == DefaultTransformerId) {
- val transformerIdentifierFromParentName = TransformerIdentifier(
- s"${parentIdentifier.name}$TransformerIdSuffix")
- queryTransformer match {
- case queryTransformer: CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] =>
- new CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] {
- override val identifier: TransformerIdentifier = transformerIdentifierFromParentName
-
- override def transform(input: Query): CandidateSourceQuery =
- queryTransformer.transform(input)
- }
- case queryTransformer: DependentCandidatePipelineQueryTransformer[
- Query,
- CandidateSourceQuery
- ] =>
- new DependentCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] {
- override val identifier: TransformerIdentifier = transformerIdentifierFromParentName
-
- override def transform(
- input: Query,
- candidates: Seq[CandidateWithDetails]
- ): CandidateSourceQuery =
- queryTransformer.transform(input, candidates)
- }
- }
- } else {
- queryTransformer
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala
deleted file mode 100644
index 80c29d7fb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.transformer
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-/**
- * A transformer for transforming a candidate pipeline's source result type into the parent's
- * mixer ore recommendation pipeline's type.
- * @tparam SourceResult The type of the result of the candidate source being used.
- * @tparam PipelineResult The type of the parent pipeline's expected
- */
-trait CandidatePipelineResultsTransformer[SourceResult, PipelineResult <: UniversalNoun[Any]]
- extends Transformer[SourceResult, PipelineResult] {
-
- override val identifier: TransformerIdentifier =
- CandidatePipelineResultsTransformer.DefaultTransformerId
-}
-
-object CandidatePipelineResultsTransformer {
- private[core] val DefaultTransformerId: TransformerIdentifier =
- TransformerIdentifier(ComponentIdentifier.BasedOnParentComponent)
- private[core] val TransformerIdSuffix = "Results"
-
- /**
- * For use when building a [[CandidatePipelineResultsTransformer]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]]
- * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]]
- */
- private[core] def copyWithUpdatedIdentifier[SourceResult, PipelineResult <: UniversalNoun[Any]](
- resultTransformer: CandidatePipelineResultsTransformer[SourceResult, PipelineResult],
- parentIdentifier: ComponentIdentifier
- ): CandidatePipelineResultsTransformer[SourceResult, PipelineResult] = {
- if (resultTransformer.identifier == DefaultTransformerId) {
- new CandidatePipelineResultsTransformer[SourceResult, PipelineResult] {
- override val identifier: TransformerIdentifier = TransformerIdentifier(
- s"${parentIdentifier.name}$TransformerIdSuffix")
-
- override def transform(input: SourceResult): PipelineResult =
- resultTransformer.transform(input)
- }
- } else {
- resultTransformer
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala
deleted file mode 100644
index 82d22d1d5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.transformer
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-/**
- * [[FeatureTransformer]] allow you to populate a [[com.twitter.product_mixer.core.feature.Feature]]s
- * value which is already available or can be derived without making an RPC.
- *
- * A [[FeatureTransformer]] transforms a given [[Inputs]] into a [[FeatureMap]].
- * The transformer must specify which [[com.twitter.product_mixer.core.feature.Feature]]s it will populate using the `features` field
- * and the returned [[FeatureMap]] must always have the specified [[com.twitter.product_mixer.core.feature.Feature]]s populated.
- *
- * @note Unlike [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] implementations,
- * an exception thrown in a [[FeatureTransformer]] will not be added to the [[FeatureMap]] and will instead be
- * bubble up to the calling pipeline's [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier]].
- */
-trait FeatureTransformer[-Inputs] extends Transformer[Inputs, FeatureMap] {
-
- def features: Set[Feature[_, _]]
-
- override val identifier: TransformerIdentifier
-
- /** Hydrates a [[FeatureMap]] for a given [[Inputs]] */
- override def transform(input: Inputs): FeatureMap
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala
deleted file mode 100644
index 8dfe0b2c4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.functional_component.transformer
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-/**
- * A transformer is a synchronous transformation that takes the provided [[Input]] and returns some
- * defined [[Output]]. For example, extracting a score from from a scored candidates.
- */
-trait Transformer[-Inputs, +Output] extends Component {
- override val identifier: TransformerIdentifier
-
- /** Takes [[Inputs]] and transformers them into some [[Output]] of your choosing. */
- def transform(input: Inputs): Output
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD
deleted file mode 100644
index fb0bf8981..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala
deleted file mode 100644
index a4bfd9e8e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.gate.DenyLoggedOutUsersGate.Suffix
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.Authentication
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.stitch.Stitch
-
-case class DenyLoggedOutUsersGate(pipelineIdentifier: ComponentIdentifier)
- extends Gate[PipelineQuery] {
- override val identifier: GateIdentifier = GateIdentifier(pipelineIdentifier + Suffix)
-
- override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = {
- if (query.getUserOrGuestId.nonEmpty) {
- Stitch.value(!query.isLoggedOut)
- } else {
- Stitch.exception(
- PipelineFailure(
- Authentication,
- "Expected either a `userId` (for logged in users) or `guestId` (for logged out users) but found neither"
- ))
- }
- }
-}
-
-object DenyLoggedOutUsersGate {
- val Suffix = "DenyLoggedOutUsers"
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala
deleted file mode 100644
index bc58ed797..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-case class ParamGate(name: String, param: Param[Boolean])(implicit file: sourcecode.File)
- extends Gate[PipelineQuery] {
-
- // From a customer-perspective, it's more useful to see the file that created the ParamGate
- override val identifier: GateIdentifier = GateIdentifier(name)(file)
-
- override def shouldContinue(query: PipelineQuery): Stitch[Boolean] =
- Stitch.value(query.params(param))
-}
-
-object ParamGate {
- val EnabledGateSuffix = "Enabled"
- val SupportedClientGateSuffix = "SupportedClient"
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala
deleted file mode 100644
index 38d735a15..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Param
-
-case class ParamNotGate(name: String, param: Param[Boolean]) extends Gate[PipelineQuery] {
- override val identifier: GateIdentifier = GateIdentifier(name)
-
- override def shouldContinue(query: PipelineQuery): Stitch[Boolean] =
- Stitch.value(!query.params(param))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD
deleted file mode 100644
index e84333ff3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-core",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-databind",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- ],
- exports = [
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-core",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-databind",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala
deleted file mode 100644
index b8c7a8e47..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.model.common
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-
-/** [[Candidate]] and it's FeatureMap */
-trait CandidateWithFeatures[+Candidate <: UniversalNoun[Any]] {
- val candidate: Candidate
- val features: FeatureMap
-}
-
-object CandidateWithFeatures {
- def unapply[Candidate <: UniversalNoun[Any]](
- candidateWithFeatures: CandidateWithFeatures[Candidate]
- ): Option[(Candidate, FeatureMap)] =
- Some(
- (candidateWithFeatures.candidate, candidateWithFeatures.features)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala
deleted file mode 100644
index 2edeb220c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.model.common
-
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.HasComponentIdentifier
-
-/**
- * Components are very generically reusable composable pieces
- * Components are uniquely identifiable and centrally registered
- */
-trait Component extends HasComponentIdentifier {
-
- /** @see [[ComponentIdentifier]] */
- override val identifier: ComponentIdentifier
-
- /** the [[Alert]]s that will be used for this component. */
- val alerts: Seq[Alert] = Seq.empty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala
deleted file mode 100644
index 3b6362849..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.core.model.common
-
-/**
- * A mixin trait that can be added to a [[Component]] that's marked with [[SupportsConditionally]]
- * A [[Component]] with [[SupportsConditionally]] and [[Conditionally]] will only be run when `onlyIf` returns true
- * if `onlyIf` returns false, the [[Component]] is skipped and no stats are recorded for it.
- *
- * @note if an exception is thrown when evaluating `onlyIf`, it will bubble up to the containing `Pipeline`,
- * however the [[Component]]'s stats will not be incremented. Because of this `onlyIf` should never throw.
- *
- * @note each [[Component]] that [[SupportsConditionally]] has an implementation with in the
- * component library that will conditionally run the component based on a [[com.twitter.timelines.configapi.Param]]
- *
- * @note [[Conditionally]] functionality is wired into the Component's Executor.
- *
- * @tparam Input the input that is used to gate a component on or off
- */
-trait Conditionally[-Input] { _: SupportsConditionally[Input] =>
-
- /**
- * if `onlyIf` returns true, the underling [[Component]] is run, otherwise it's skipped
- * @note must not throw
- */
- def onlyIf(query: Input): Boolean
-}
-
-/**
- * Marker trait added to the base type for each [[Component]] which supports the [[Conditionally]] mixin
- *
- * @note this is `private[core]` because it can only be added to the base implementation of components by the Product Mixer team
- *
- * @tparam Input the input that is used to gate a component on or off if [[Conditionally]] is mixed in
- */
-private[core] trait SupportsConditionally[-Input] { _: Component => }
-
-object Conditionally {
-
- /**
- * Helper method for combining the [[Conditionally.onlyIf]] of an underlying [[Component]] with an additional predicate
- */
- def and[ComponentType <: Component, Input](
- query: Input,
- component: ComponentType with SupportsConditionally[Input],
- onlyIf: Boolean
- ): Boolean =
- onlyIf && {
- component match {
- // @unchecked is safe here because the type parameter is guaranteed by
- // the `SupportsConditionally[Input]` type parameter
- case underlying: Conditionally[Input @unchecked] =>
- underlying.onlyIf(query)
- case _ =>
- true
- }
- }
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala
deleted file mode 100644
index 68acda414..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.common
-
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-
-@JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME)
-trait UniversalNoun[+T] extends Equals {
- def id: T
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD
deleted file mode 100644
index 16504ded3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/lihaoyi:sourcecode",
- "util/util-core",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
- exports = [
- "3rdparty/jvm/com/lihaoyi:sourcecode",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala
deleted file mode 100644
index 1ad6ec144..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Candidate Pipeline identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class CandidatePipelineIdentifier(override val name: String)
- extends ComponentIdentifier("CandidatePipeline", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CandidatePipelineIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: CandidatePipelineIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object CandidatePipelineIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): CandidatePipelineIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new CandidatePipelineIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal CandidatePipelineIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala
deleted file mode 100644
index b83cb011d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Candidate Source identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class CandidateSourceIdentifier(override val name: String)
- extends ComponentIdentifier("CandidateSource", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[CandidateSourceIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: CandidateSourceIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object CandidateSourceIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): CandidateSourceIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new CandidateSourceIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal CandidateSourceIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala
deleted file mode 100644
index a95973ea2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.twitter.conversions.StringOps
-import scala.util.matching.Regex
-
-/**
- * Component Identifiers are a type of identifier used in product mixer to identify
- * unique components - products, pipelines, candidate sources.
- *
- * Each identifier has two parts - a type and a name. Subclasses of [[ComponentIdentifier]]
- * should hardcode the `componentType`, and be declared in this file.
- *
- * For example, a [[ProductPipelineIdentifier]] has the type "ProductPipeline".
- *
- * Component identifiers are used in:
- * - Logs
- * - Tooling
- * - Metrics
- * - Feature Switches
- *
- * A component identifier name is restricted to:
- * - 3 to 80 characters to ensure reasonable length
- * - A-Z, a-z, and Digits
- * - Must start with A-Z
- * - Digits only on the ends of "words"
- * - Examples include "AlphaSample" and "UsersLikeMe"
- * - and "SimsV2" or "Test6"
- *
- * Avoid including types like "Pipeline", "MixerPipeline" etc in your identifier. these
- * can be implied by the type itself, and will automatically be used where appropriate (logs etc).
- */
-@JsonSerialize(using = classOf[ComponentIdentifierSerializer])
-abstract class ComponentIdentifier(
- val componentType: String,
- val name: String)
- extends Equals {
-
- val file: sourcecode.File = ""
-
- override val toString: String = s"$name$componentType"
-
- val snakeCase: String = StringOps.toSnakeCase(toString)
-
- val toScopes: Seq[String] = Seq(componentType, name)
-}
-
-object ComponentIdentifier {
- // Allows for CamelCase and CamelCaseVer3 styles
- val AllowedCharacters: Regex = "([A-Z][A-Za-z]*[0-9]*)+".r
- val MinLength = 3
- val MaxLength = 80
-
- /**
- * When a [[ComponentIdentifier.name]] is [[BasedOnParentComponent]]
- * then when operations that depend on the [[ComponentIdentifier]]
- * are performed, like registering and stats, we will perform that
- * operation by substituting the [[ComponentIdentifier.name]] with
- * the parent component's [[ComponentIdentifier.name]].
- */
- private[core] val BasedOnParentComponent = "BasedOnParentComponent"
-
- def isValidName(name: String): Boolean = {
- name match {
- case n if n.length < MinLength =>
- false
- case n if n.length > MaxLength =>
- false
- case AllowedCharacters(_*) =>
- true
- case _ =>
- false
- }
- }
-
- implicit val ordering: Ordering[ComponentIdentifier] =
- Ordering.by { component =>
- val componentTypeRank = component match {
- case _: ProductIdentifier => 0
- case _: ProductPipelineIdentifier => 1
- case _: MixerPipelineIdentifier => 2
- case _: RecommendationPipelineIdentifier => 3
- case _: ScoringPipelineIdentifier => 4
- case _: CandidatePipelineIdentifier => 5
- case _: PipelineStepIdentifier => 6
- case _: CandidateSourceIdentifier => 7
- case _: FeatureHydratorIdentifier => 8
- case _: GateIdentifier => 9
- case _: FilterIdentifier => 10
- case _: TransformerIdentifier => 11
- case _: ScorerIdentifier => 12
- case _: DecoratorIdentifier => 13
- case _: DomainMarshallerIdentifier => 14
- case _: TransportMarshallerIdentifier => 15
- case _: SideEffectIdentifier => 16
- case _: PlatformIdentifier => 17
- case _: SelectorIdentifier => 18
- case _ => Int.MaxValue
- }
-
- // First rank by type, then by name for equivalent types for overall order stability
- (componentTypeRank, component.name)
- }
-}
-
-/**
- * HasComponentIdentifier indicates that component has a [[ComponentIdentifier]]
- */
-trait HasComponentIdentifier {
- val identifier: ComponentIdentifier
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala
deleted file mode 100644
index a9c2cac6a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-
-private[identifier] class ComponentIdentifierSerializer()
- extends JsonSerializer[ComponentIdentifier] {
-
- private case class SerializableComponentIdentifier(
- identifier: String,
- sourceFile: String)
-
- override def serialize(
- componentIdentifier: ComponentIdentifier,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit = serializers.defaultSerializeValue(
- SerializableComponentIdentifier(componentIdentifier.toString, componentIdentifier.file.value),
- gen)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala
deleted file mode 100644
index 663e3a3dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-
-/**
- * A non-empty immutable stack of [[ComponentIdentifier]]s
- *
- * [[ComponentIdentifierStack]] does not support removing [[ComponentIdentifier]]s,
- * instead a [[ComponentIdentifierStack]] should be used by adding new [[ComponentIdentifier]]s
- * as processing enters a given `Component`, then discarded after.
- * Think of this as similar to a let-scoped variable, where the let-scope is the given component.
- */
-@JsonSerialize(using = classOf[ComponentIdentifierStackSerializer])
-class ComponentIdentifierStack private (val componentIdentifiers: List[ComponentIdentifier]) {
-
- /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]] added at the top */
- def push(newComponentIdentifier: ComponentIdentifier): ComponentIdentifierStack =
- new ComponentIdentifierStack(newComponentIdentifier :: componentIdentifiers)
-
- /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]]s added at the top */
- def push(newComponentIdentifiers: ComponentIdentifierStack): ComponentIdentifierStack =
- new ComponentIdentifierStack(
- newComponentIdentifiers.componentIdentifiers ::: componentIdentifiers)
-
- /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]]s added at the top */
- def push(newComponentIdentifiers: Option[ComponentIdentifierStack]): ComponentIdentifierStack = {
- newComponentIdentifiers match {
- case Some(newComponentIdentifiers) => push(newComponentIdentifiers)
- case None => this
- }
- }
-
- /** Return the top element of the [[ComponentIdentifierStack]] */
- val peek: ComponentIdentifier = componentIdentifiers.head
-
- /** Return the size of the [[ComponentIdentifierStack]] */
- def size: Int = componentIdentifiers.length
-
- override def toString: String =
- s"ComponentIdentifierStack(componentIdentifiers = $componentIdentifiers)"
-
- override def equals(obj: Any): Boolean = {
- obj match {
- case componentIdentifierStack: ComponentIdentifierStack
- if componentIdentifierStack.eq(this) ||
- componentIdentifierStack.componentIdentifiers == componentIdentifiers =>
- true
- case _ => false
- }
- }
-}
-
-object ComponentIdentifierStack {
-
- /**
- * Returns a [[ComponentIdentifierStack]] from the given [[ComponentIdentifier]]s,
- * where the top of the stack is the left-most [[ComponentIdentifier]]
- */
- def apply(
- componentIdentifier: ComponentIdentifier,
- componentIdentifierStack: ComponentIdentifier*
- ) =
- new ComponentIdentifierStack(componentIdentifier :: componentIdentifierStack.toList)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala
deleted file mode 100644
index da8855df1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-
-private[identifier] class ComponentIdentifierStackSerializer()
- extends JsonSerializer[ComponentIdentifierStack] {
- override def serialize(
- componentIdentifierStack: ComponentIdentifierStack,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit = serializers.defaultSerializeValue(componentIdentifierStack.componentIdentifiers, gen)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala
deleted file mode 100644
index 3a9cfef88..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Decorator identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class DecoratorIdentifier(override val name: String)
- extends ComponentIdentifier("Decorator", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DecoratorIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: DecoratorIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object DecoratorIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): DecoratorIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new DecoratorIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal DecoratorIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala
deleted file mode 100644
index b0b22bb16..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Domain Marshaller identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class DomainMarshallerIdentifier(override val name: String)
- extends ComponentIdentifier("DomainMarshaller", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[DomainMarshallerIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: DomainMarshallerIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object DomainMarshallerIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): DomainMarshallerIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new DomainMarshallerIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal DomainMarshallerIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala
deleted file mode 100644
index 46ace3cbd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Feature Hydrator identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class FeatureHydratorIdentifier(override val name: String)
- extends ComponentIdentifier("FeatureHydrator", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[FeatureHydratorIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: FeatureHydratorIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object FeatureHydratorIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): FeatureHydratorIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new FeatureHydratorIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal FeatureHydratorIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala
deleted file mode 100644
index 2b5c2113e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Filter identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class FilterIdentifier(override val name: String)
- extends ComponentIdentifier("Filter", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[FilterIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: FilterIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object FilterIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): FilterIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new FilterIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal FilterIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala
deleted file mode 100644
index 19309aa21..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Gate identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class GateIdentifier(override val name: String)
- extends ComponentIdentifier("Gate", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[GateIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: GateIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object GateIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): GateIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new GateIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal GateIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala
deleted file mode 100644
index 696dc4ff1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Mixer Pipeline identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class MixerPipelineIdentifier(override val name: String)
- extends ComponentIdentifier("MixerPipeline", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[MixerPipelineIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: MixerPipelineIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object MixerPipelineIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): MixerPipelineIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new MixerPipelineIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal MixerPipelineIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala
deleted file mode 100644
index 5df48e069..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Pipeline Step identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class PipelineStepIdentifier(
- override val name: String)
- extends ComponentIdentifier("Step", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[PipelineStepIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: PipelineStepIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-class Person(val name: String, val age: Int) extends Equals {
- override def canEqual(that: Any): Boolean =
- that.isInstanceOf[Person]
-
- //Intentionally avoiding the call to super.equals because no ancestor has overridden equals (see note 7 below)
- override def equals(that: Any): Boolean =
- that match {
- case person: Person =>
- (this eq person) || (hashCode == person.hashCode) && ((name == person.name) && (age == person.age))
-
- case _ =>
- false
- }
-
- //Intentionally avoiding the call to super.hashCode because no ancestor has overridden hashCode (see note 7 below)
- override def hashCode(): Int =
- 31 * (
- name.##
- ) + age.##
-}
-
-object PipelineStepIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): PipelineStepIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new PipelineStepIdentifier(name) { override val file: sourcecode.File = sourceFile }
- else
- throw new IllegalArgumentException(s"Illegal StepIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala
deleted file mode 100644
index 47a0c57e2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * [[ComponentIdentifier]] type used by internal parts of Product Mixer that need to be identified
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class PlatformIdentifier(override val name: String)
- extends ComponentIdentifier("Platform", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[PlatformIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: PlatformIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object PlatformIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): PlatformIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new PlatformIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal PlatformIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala
deleted file mode 100644
index 681be8c9d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Product identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class ProductIdentifier(override val name: String)
- extends ComponentIdentifier("Product", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ProductIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: ProductIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object ProductIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): ProductIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new ProductIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal ProductIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala
deleted file mode 100644
index 21a8ca26d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Product Pipeline identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class ProductPipelineIdentifier(override val name: String)
- extends ComponentIdentifier("ProductPipeline", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ProductPipelineIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: ProductPipelineIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object ProductPipelineIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): ProductPipelineIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new ProductPipelineIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal ProductPipelineIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala
deleted file mode 100644
index f10e6d28d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Recommendation Pipeline identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class RecommendationPipelineIdentifier(override val name: String)
- extends ComponentIdentifier("RecommendationPipeline", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[RecommendationPipelineIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: RecommendationPipelineIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object RecommendationPipelineIdentifier {
- def apply(
- name: String
- )(
- implicit sourceFile: sourcecode.File
- ): RecommendationPipelineIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new RecommendationPipelineIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal RecommendationPipelineIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala
deleted file mode 100644
index 5d55c6422..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Root identifier used as the root identifier for products during component registration
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class RootIdentifier extends ComponentIdentifier("Root", "") {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[RootIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: RootIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object RootIdentifier {
- def apply()(implicit sourceFile: sourcecode.File): RootIdentifier = {
- new RootIdentifier() {
- override val file: sourcecode.File = sourceFile
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala
deleted file mode 100644
index 3caee298f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Scorer identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class ScorerIdentifier(override val name: String)
- extends ComponentIdentifier("Scorer", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ScorerIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: ScorerIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object ScorerIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): ScorerIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new ScorerIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal ScorerIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala
deleted file mode 100644
index 3b2fbdb86..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Scoring Pipeline identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class ScoringPipelineIdentifier(override val name: String)
- extends ComponentIdentifier("ScoringPipeline", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[ScoringPipelineIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: ScoringPipelineIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object ScoringPipelineIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): ScoringPipelineIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new ScoringPipelineIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal ScoringPipelineIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala
deleted file mode 100644
index 5e04d394b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Selector identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class SelectorIdentifier(override val name: String)
- extends ComponentIdentifier("Selector", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[SelectorIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: SelectorIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-/**
- * Used in `SelectorExecutor` to give an ID to each selector in the `ComponentIdentifierStack`
- *
- * These are often generated automatically in the executor and are dependent on the class names
- * so we skip validation to avoid issues. Since we dont record stats for Selectors this is okay.
- */
-private[core] object SelectorIdentifier {
- def apply(
- name: String,
- index: Int
- )(
- implicit sourceFile: sourcecode.File
- ): SelectorIdentifier = {
- val capitalizedWithoutSpecialCharacters = name.replace("$", "").capitalize
- new SelectorIdentifier(index.toString + capitalizedWithoutSpecialCharacters) {
- override val file: sourcecode.File = sourceFile
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala
deleted file mode 100644
index 4775721b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Side Effect identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class SideEffectIdentifier(override val name: String)
- extends ComponentIdentifier("SideEffect", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[SideEffectIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: SideEffectIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object SideEffectIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): SideEffectIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new SideEffectIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal SideEffectIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala
deleted file mode 100644
index e336c4460..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Transformer identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class TransformerIdentifier(override val name: String)
- extends ComponentIdentifier("Transformer", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TransformerIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: TransformerIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object TransformerIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): TransformerIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new TransformerIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal TransformerIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala
deleted file mode 100644
index 07f7d8d76..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.model.common.identifier
-
-/**
- * Transport Marshaller identifier
- *
- * @note This class should always remain effectively `final`. If for any reason the `sealed`
- * modifier is removed, the equals() implementation must be updated in order to handle class
- * inheritor equality (see note on the equals method below)
- */
-sealed abstract class TransportMarshallerIdentifier(override val name: String)
- extends ComponentIdentifier("TransportMarshaller", name) {
-
- /**
- * @inheritdoc
- */
- override def canEqual(that: Any): Boolean = that.isInstanceOf[TransportMarshallerIdentifier]
-
- /**
- * High performance implementation of equals method that leverages:
- * - Referential equality short circuit
- * - Cached hashcode equality short circuit
- * - Field values are only checked if the hashCodes are equal to handle the unlikely case
- * of a hashCode collision
- * - Removal of check for `that` being an equals-compatible descendant since this class is final
- *
- * @note `candidate.canEqual(this)` is not necessary because this class is final
- * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala,
- * Chapter 28]] for discussion and design.
- */
- override def equals(that: Any): Boolean =
- that match {
- case identifier: TransportMarshallerIdentifier =>
- // Note identifier.canEqual(this) is not necessary because this class is effectively final
- ((this eq identifier)
- || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name))))
- case _ =>
- false
- }
-
- /**
- * Leverage domain-specific constraints (see notes below) to safely construct and cache the
- * hashCode as a val, such that it is instantiated once on object construction. This prevents the
- * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the
- * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field
- * object mutability and hashCode implementations.
- *
- * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode
- * are immutable. This includes:
- * - Inability to mutate the object reference on for an existing instantiated identifier
- * (i.e. each field is a val)
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * - Inability to mutate the field object instance itself (i.e. each field is an immutable
- * data structure), assuming stable hashCode implementations for these objects
- *
- * @note In order for the hashCode to be consistent with object equality, `##` must be used for
- * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`.
- */
- override val hashCode: Int = 31 * componentType.## + name.##
-}
-
-object TransportMarshallerIdentifier {
- def apply(name: String)(implicit sourceFile: sourcecode.File): TransportMarshallerIdentifier = {
- if (ComponentIdentifier.isValidName(name))
- new TransportMarshallerIdentifier(name) {
- override val file: sourcecode.File = sourceFile
- }
- else
- throw new IllegalArgumentException(s"Illegal TransportMarshallerIdentifier: $name")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD
deleted file mode 100644
index 506c23b1b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala
deleted file mode 100644
index 65f476af5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import scala.collection.immutable.ListSet
-
-/**
- * A list set of all the candidate pipelines a candidate originated from. This is typically a
- * single element set, but merging candidates across pipelines using
- * [[com.twitter.product_mixer.component_library.selector.CombineFeatureMapsCandidateMerger]]
- * will merge sets for the candidate. The last element of the set is the first pipeline identifier
- * as we prepend new ones since we want O(1) access for the last element.
- */
-object CandidatePipelines extends Feature[UniversalNoun[Any], ListSet[CandidatePipelineIdentifier]]
-
-/**
- * A list set of all the candidate sources a candidate originated from. This is typically a
- * single element set, but merging candidates across pipelines using
- * [[com.twitter.product_mixer.component_library.selector.CombineFeatureMapsCandidateMerger]]
- * will merge sets for the candidate. The last element of the set is the first source identifier
- * as we prepend new ones since we want O(1) access for the last element.
- */
-object CandidateSources extends Feature[UniversalNoun[Any], ListSet[CandidateSourceIdentifier]]
-
-/**
- * The source position relative to all candidates the originating candidate source a candidate
- * came from. When merged with other candidates, the position from the first candidate source
- * takes priority.
- */
-object CandidateSourcePosition extends Feature[UniversalNoun[Any], Int]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala
deleted file mode 100644
index ff6297a92..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult
-import scala.collection.immutable.ListSet
-import scala.reflect.ClassTag
-
-sealed trait CandidateWithDetails { self =>
- def presentation: Option[UniversalPresentation]
- def features: FeatureMap
-
- // last of the set because in ListSet, the last element is the first inserted one with O(1)
- // access
- lazy val source: CandidatePipelineIdentifier = features.get(CandidatePipelines).last
- lazy val sourcePosition: Int = features.get(CandidateSourcePosition)
-
- /**
- * @see [[getCandidateId]]
- */
- def candidateIdLong: Long = getCandidateId[Long]
-
- /**
- * @see [[getCandidateId]]
- */
- def candidateIdString: String = getCandidateId[String]
-
- /**
- * Convenience method for retrieving a candidate ID off of the base [[CandidateWithDetails]] trait
- * without manually pattern matching.
- *
- * @throws PipelineFailure if CandidateIdType does not match the expected Item Candidate Id type,
- * or if invoked on a Module Candidate
- */
- def getCandidateId[CandidateIdType](
- )(
- implicit tag: ClassTag[CandidateIdType]
- ): CandidateIdType =
- self match {
- case item: ItemCandidateWithDetails =>
- item.candidate.id match {
- case id: CandidateIdType => id
- case _ =>
- throw PipelineFailure(
- UnexpectedCandidateResult,
- s"Invalid Item Candidate ID type expected $tag for Item Candidate type ${item.candidate.getClass}")
- }
- case _: ModuleCandidateWithDetails =>
- throw PipelineFailure(
- UnexpectedCandidateResult,
- "Cannot retrieve Item Candidate ID for a Module")
- }
-
- /**
- * Convenience method for retrieving a candidate off of the base [[CandidateWithDetails]] trait
- * without manually pattern matching.
- *
- * @throws PipelineFailure if CandidateType does not match the expected Item Candidate type, or
- * if invoked on a Module Candidate
- */
- def getCandidate[CandidateType <: UniversalNoun[_]](
- )(
- implicit tag: ClassTag[CandidateType]
- ): CandidateType =
- self match {
- case ItemCandidateWithDetails(candidate: CandidateType, _, _) => candidate
- case item: ItemCandidateWithDetails =>
- throw PipelineFailure(
- UnexpectedCandidateResult,
- s"Invalid Item Candidate type expected $tag for Item Candidate type ${item.candidate.getClass}")
- case _: ModuleCandidateWithDetails =>
- throw PipelineFailure(
- UnexpectedCandidateResult,
- "Cannot retrieve Item Candidate for a Module")
- }
-
- /**
- * Convenience method for checking if this contains a certain candidate type
- *
- * @throws PipelineFailure if CandidateType does not match the expected Item Candidate type, or
- * if invoked on a Module Candidate
- */
- def isCandidateType[CandidateType <: UniversalNoun[_]](
- )(
- implicit tag: ClassTag[CandidateType]
- ): Boolean = self match {
- case ItemCandidateWithDetails(_: CandidateType, _, _) => true
- case _ => false
- }
-}
-
-case class ItemCandidateWithDetails(
- override val candidate: UniversalNoun[Any],
- presentation: Option[UniversalPresentation],
- override val features: FeatureMap)
- extends CandidateWithDetails
- with CandidateWithFeatures[UniversalNoun[Any]]
-
-case class ModuleCandidateWithDetails(
- candidates: Seq[ItemCandidateWithDetails],
- presentation: Option[ModulePresentation],
- override val features: FeatureMap)
- extends CandidateWithDetails
-
-object ItemCandidateWithDetails {
- def apply(
- candidate: UniversalNoun[Any],
- presentation: Option[UniversalPresentation],
- source: CandidatePipelineIdentifier,
- sourcePosition: Int,
- features: FeatureMap
- ): ItemCandidateWithDetails = {
- val newFeatureMap =
- FeatureMapBuilder()
- .add(CandidateSourcePosition, sourcePosition)
- .add(CandidatePipelines, ListSet.empty + source).build() ++ features
- ItemCandidateWithDetails(candidate, presentation, newFeatureMap)
- }
-}
-
-object ModuleCandidateWithDetails {
- def apply(
- candidates: Seq[ItemCandidateWithDetails],
- presentation: Option[ModulePresentation],
- source: CandidatePipelineIdentifier,
- sourcePosition: Int,
- features: FeatureMap
- ): ModuleCandidateWithDetails = {
- val newFeatureMap =
- FeatureMapBuilder()
- .add(CandidateSourcePosition, sourcePosition)
- .add(CandidatePipelines, ListSet.empty + source).build() ++ features
-
- ModuleCandidateWithDetails(candidates, presentation, newFeatureMap)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala
deleted file mode 100644
index 93f86e2b4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation
-
-trait ItemPresentation extends UniversalPresentation {
- // Optional field which if populated, will group the items into the specified module
- def modulePresentation: Option[ModulePresentation] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala
deleted file mode 100644
index dff815c8a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation
-
-trait ModulePresentation extends UniversalPresentation
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala
deleted file mode 100644
index d206c5b23..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation
-
-/**
- * Encapsulates information about how to present a Candidate
- *
- * Implementations of a [[UniversalPresentation]] contain information about how to present the Candidate.
- * This extra information can be in fields in the implementations or in their types.
- *
- * For instance, a Tweet candidate that will be displayed as a URT Tweet Item will be decorated with a
- * [[UniversalPresentation]] implementation that reflects the presentation such as
- * [[com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation]]
- *
- * @see [[com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator]] for associating a
- * [[UniversalPresentation]] with a Candidate.
- */
-trait UniversalPresentation
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD
deleted file mode 100644
index 67ebe01c4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala
deleted file mode 100644
index dedb450ce..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.slice
-
-import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem
-
-trait BaseSliceItemPresentation extends ItemPresentation {
- def sliceItem: SliceItem
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD
deleted file mode 100644
index b9923428d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala
deleted file mode 100644
index 7e1f87bef..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-trait BaseUrtItemPresentation extends ItemPresentation {
-
- def timelineItem: TimelineItem
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala
deleted file mode 100644
index d1a774499..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule
-
-trait BaseUrtModulePresentation extends ModulePresentation {
- def timelineModule: TimelineModule
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala
deleted file mode 100644
index 0d0a74da3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.urt
-
-import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation
-
-trait BaseUrtOperationPresentation extends ItemPresentation {
-
- def timelineOperation: TimelineOperation
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala
deleted file mode 100644
index 33ff69c21..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.urt
-
-/**
- * Whether an item is considered dispensable within a module.
- * Dispensable module items should never be left as the final remaining
- * items within a module. Whenever a module would be left with only
- * dispensable contents (through removal or dismissal of other items) the
- * entire module should be discarded as if contained 0 items.
- *
- * @see http://go/urtDispensableModuleItems
- */
-trait IsDispensable { self: BaseUrtItemPresentation =>
- def dispensable: Boolean
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala
deleted file mode 100644
index 0235a20de..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.common.presentation.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay
-
-/*
- * Tree state declaring item’s parent relationship with any other items in
- * the module, any display indentation information, and/or collapsed display state.
- */
-trait WithItemTreeDisplay { self: BaseUrtItemPresentation =>
- def treeDisplay: Option[ModuleItemTreeDisplay]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD
deleted file mode 100644
index c9ed8c7eb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD
+++ /dev/null
@@ -1,8 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala
deleted file mode 100644
index 5158523ee..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling
-
-trait HasMarshalling
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD
deleted file mode 100644
index 790abac6d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/fasterxml/jackson:jackson-module-scala",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "configapi/configapi-core/src/main/scala/com/twitter/timelines/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "util/util-core:util-core-util",
- ],
- exports = [
- "3rdparty/jvm/com/fasterxml/jackson:jackson-module-scala",
- "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations",
- "configapi/configapi-core/src/main/scala/com/twitter/timelines/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "util/util-core:util-core-util",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala
deleted file mode 100644
index 31ba2ad04..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-import com.fasterxml.jackson.annotation.JsonIgnore
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-
-/**
- * ClientContext contains fields related to the client making the request.
- */
-case class ClientContext(
- userId: Option[Long],
- guestId: Option[Long],
- guestIdAds: Option[Long],
- guestIdMarketing: Option[Long],
- appId: Option[Long],
- ipAddress: Option[String],
- userAgent: Option[String],
- countryCode: Option[String],
- languageCode: Option[String],
- isTwoffice: Option[Boolean],
- userRoles: Option[Set[String]],
- deviceId: Option[String],
- mobileDeviceId: Option[String],
- mobileDeviceAdId: Option[String],
- limitAdTracking: Option[Boolean])
-
-object ClientContext {
- val empty: ClientContext = ClientContext(
- userId = None,
- guestId = None,
- guestIdAds = None,
- guestIdMarketing = None,
- appId = None,
- ipAddress = None,
- userAgent = None,
- countryCode = None,
- languageCode = None,
- isTwoffice = None,
- userRoles = None,
- deviceId = None,
- mobileDeviceId = None,
- mobileDeviceAdId = None,
- limitAdTracking = None
- )
-}
-
-/**
- * HasClientContext indicates that a request has [[ClientContext]] and adds helper functions for
- * accessing [[ClientContext]] fields.
- */
-trait HasClientContext {
- def clientContext: ClientContext
-
- /**
- * getRequiredUserId returns a userId and throw if it's missing.
- *
- * @note logged out requests are disabled by default so this is safe for most products
- */
- @JsonIgnore /** Jackson tries to serialize this method, throwing an exception for guest products */
- def getRequiredUserId: Long = clientContext.userId.getOrElse(
- throw PipelineFailure(BadRequest, "Missing required field: userId"))
-
- /**
- * getOptionalUserId returns a userId if one is set
- */
- def getOptionalUserId: Option[Long] = clientContext.userId
-
- /**
- * getUserIdLoggedOutSupport returns a userId and falls back to 0 if none is set
- */
- def getUserIdLoggedOutSupport: Long = clientContext.userId.getOrElse(0L)
-
- /**
- * getUserOrGuestId returns a userId or a guestId if no userId has been set
- */
- def getUserOrGuestId: Option[Long] = clientContext.userId.orElse(clientContext.guestId)
-
- /**
- * getCountryCode returns a country code if one is set
- */
- def getCountryCode: Option[String] = clientContext.countryCode
-
- /**
- * getLanguageCode returns a language code if one is set
- */
- def getLanguageCode: Option[String] = clientContext.languageCode
-
- /**
- * isLoggedOut returns true if the user is logged out (no userId present).
- *
- * @note this can be useful in conjunction with [[getUserIdLoggedOutSupport]]
- */
- def isLoggedOut: Boolean = clientContext.userId.isEmpty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala
deleted file mode 100644
index 7347e333b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-import com.twitter.util.Time
-
-trait DebugOptions {
- // Manually override the request time which is useful for writing deterministic Feature tests,
- // since Feature tests do not support mocking Time. For example, URT sort indexes start with a
- // Snowflake ID based on request time if no initialSortIndex is set on the request cursor, so to
- // write a Feature test for this scenario, we can manually set the request time to use here.
- def requestTimeOverride: Option[Time] = None
-}
-
-trait HasDebugOptions {
- def debugOptions: Option[DebugOptions]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala
deleted file mode 100644
index 1c951cbf3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-import com.twitter.timelines.configapi.{FeatureValue => ConfigApiFeatureValue}
-
-case class DebugParams(
- featureOverrides: Option[Map[String, ConfigApiFeatureValue]],
- override val debugOptions: Option[DebugOptions])
- extends HasDebugOptions
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala
deleted file mode 100644
index 40f60fc7c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-/**
- * Allow clients to pass in a set of IDs that would be excluded from the results.
- */
-trait HasExcludedIds {
- val excludedIds: Set[Long] = Set.empty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala
deleted file mode 100644
index e52f2bcde..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-/**
- * serializedRequestCursor is any serialized representation of a cursor.
- *
- * The serialized representation is implementation-specific but will often be a base 64
- * representation of a Thrift struct. Cursors should not be deserialized in the unmarshaller.
- */
-trait HasSerializedRequestCursor {
- def serializedRequestCursor: Option[String]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala
deleted file mode 100644
index 7afb2eefe..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier
-
-trait Product extends Component {
-
- /**
- * Identifier names on products can be used to create Feature Switch rules by product,
- * which useful if bucketing occurs in a component shared by multiple products.
- *
- * @see [[com.twitter.product_mixer.core.product.ProductParamConfig.supportedClientFSName]]
- */
- override val identifier: ProductIdentifier
-
- /**
- * To support StringCenter, override this val to `Some("name-of-string-center-project")` and
- * include the `ProductScopeStringCenterModule` in the server's modules list
- */
- val stringCenterProject: Option[String] = None
-}
-
-trait HasProduct {
- def product: Product
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala
deleted file mode 100644
index 71a0d66ea..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-trait ProductContext
-
-trait HasProductContext {
- def productContext: Option[ProductContext]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala
deleted file mode 100644
index 7dfcf4e4d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.request
-
-trait Request
- extends HasClientContext
- with HasProduct
- with HasProductContext
- with HasSerializedRequestCursor {
- def maxResults: Option[Int]
- def debugParams: Option[DebugParams]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD
deleted file mode 100644
index e37672b5c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala
deleted file mode 100644
index b0709285a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level
-
-/*
- These are model objects for the thrift enum - src/thrift/com/twitter/spam/rtf/safety_level.thrift
- Please add new objects as needed for the marhallers
- */
-sealed trait SafetyLevel
-
-case object ConversationFocalTweetSafetyLevel extends SafetyLevel
-case object ConversationReplySafetyLevel extends SafetyLevel
-case object ConversationInjectedTweetSafetyLevel extends SafetyLevel
-case object TimelineFocalTweetSafetyLevel extends SafetyLevel
-case object TimelineHomePromotedHydrationSafetyLevel extends SafetyLevel
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD
deleted file mode 100644
index e37672b5c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala
deleted file mode 100644
index 5891027a6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.slice
-
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-
-/**
- * These are the Ad Types exposed on AdUnits
- *
- * They are to be kept in sync with strato/config/src/thrift/com/twitter/strato/graphql/hubble.thrift
- */
-sealed trait AdType
-object AdType {
- case object Tweet extends AdType
- case object Account extends AdType
- case object InStreamVideo extends AdType
- case object DisplayCreative extends AdType
- case object Trend extends AdType
- case object Spotlight extends AdType
- case object Takeover extends AdType
-}
-
-trait SliceItem
-case class TweetItem(id: Long) extends SliceItem
-case class UserItem(id: Long) extends SliceItem
-case class TwitterListItem(id: Long) extends SliceItem
-case class DMConvoSearchItem(id: String, lastReadableEventId: Option[Long]) extends SliceItem
-case class DMEventItem(id: Long) extends SliceItem
-case class DMConvoItem(id: String, lastReadableEventId: Option[Long]) extends SliceItem
-case class DMMessageSearchItem(id: Long) extends SliceItem
-case class TopicItem(id: Long) extends SliceItem
-case class TypeaheadEventItem(eventId: Long, metadata: Option[TypeaheadMetadata]) extends SliceItem
-case class TypeaheadQuerySuggestionItem(query: String, metadata: Option[TypeaheadMetadata])
- extends SliceItem
-case class TypeaheadUserItem(
- userId: Long,
- metadata: Option[TypeaheadMetadata],
- badges: Seq[UserBadge])
- extends SliceItem
-case class AdItem(adUnitId: Long, adAccountId: Long) extends SliceItem
-case class AdCreativeItem(creativeId: Long, adType: AdType, adAccountId: Long) extends SliceItem
-case class AdGroupItem(adGroupId: Long, adAccountId: Long) extends SliceItem
-case class CampaignItem(campaignId: Long, adAccountId: Long) extends SliceItem
-case class FundingSourceItem(fundingSourceId: Long, adAccountId: Long) extends SliceItem
-
-sealed trait CursorType
-case object PreviousCursor extends CursorType
-case object NextCursor extends CursorType
-@deprecated(
- "GapCursors are not supported by Product Mixer Slice marshallers, if you need support for these reach out to #product-mixer")
-case object GapCursor extends CursorType
-
-// CursorItem extends SliceItem to enable support for GapCursors
-case class CursorItem(value: String, cursorType: CursorType) extends SliceItem
-
-case class SliceInfo(
- previousCursor: Option[String],
- nextCursor: Option[String])
-
-case class Slice(
- items: Seq[SliceItem],
- sliceInfo: SliceInfo)
- extends HasMarshalling
-
-sealed trait TypeaheadResultContextType
-case object You extends TypeaheadResultContextType
-case object Location extends TypeaheadResultContextType
-case object NumFollowers extends TypeaheadResultContextType
-case object FollowRelationship extends TypeaheadResultContextType
-case object Bio extends TypeaheadResultContextType
-case object NumTweets extends TypeaheadResultContextType
-case object Trending extends TypeaheadResultContextType
-case object HighlightedLabel extends TypeaheadResultContextType
-
-case class TypeaheadResultContext(
- contextType: TypeaheadResultContextType,
- displayString: String,
- iconUrl: Option[String])
-
-case class TypeaheadMetadata(
- score: Double,
- source: Option[String],
- context: Option[TypeaheadResultContext])
-
-// Used to render badges in Typeahead, such as Business-affiliated badges
-case class UserBadge(badgeType: String, badgeUrl: String, description: String)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD
deleted file mode 100644
index b0c058fe3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala
deleted file mode 100644
index df9656f85..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-
-case class Page(
- id: String,
- pageBody: PageBody,
- scribeConfig: Option[TimelineScribeConfig] = None,
- pageHeader: Option[PageHeader] = None,
- pageNavBar: Option[PageNavBar] = None)
- extends HasMarshalling
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala
deleted file mode 100644
index 8f3a0ff96..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-sealed trait PageBody
-
-case class TimelineKeyPageBody(timeline: TimelineKey) extends PageBody
-
-case class SegmentedTimelinesPageBody(
- initialTimeline: SegmentedTimeline,
- timelines: Seq[SegmentedTimeline])
- extends PageBody
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala
deleted file mode 100644
index b39b36a99..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo
-
-sealed trait PageHeader
-
-case class TopicPageHeader(
- topicId: String,
- facepile: Option[TopicPageHeaderFacepile] = None,
- override val clientEventInfo: Option[ClientEventInfo] = None,
- landingContext: Option[String] = None,
- displayType: Option[TopicPageHeaderDisplayType] = Some(BasicTopicPageHeaderDisplayType))
- extends PageHeader
- with HasClientEventInfo
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala
deleted file mode 100644
index ee1d4d554..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo
-
-sealed trait PageNavBar
-
-case class TopicPageNavBar(
- topicId: String,
- override val clientEventInfo: Option[ClientEventInfo] = None)
- extends PageNavBar
- with HasClientEventInfo
-
-case class TitleNavBar(
- title: String,
- subtitle: Option[String] = None,
- override val clientEventInfo: Option[ClientEventInfo] = None)
- extends PageNavBar
- with HasClientEventInfo
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala
deleted file mode 100644
index a727376f4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig
-
-case class SegmentedTimeline(
- id: String,
- labelText: String,
- timeline: TimelineKey,
- scribeConfig: Option[TimelineScribeConfig] = None,
- refreshIntervalSec: Option[Long] = None)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala
deleted file mode 100644
index 6146693d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-sealed trait TimelineKey
-
-case class TopicsLandingTimeline(topicId: Option[String]) extends TimelineKey
-
-case class NoteworthyAccountsTimeline(topicId: Option[String]) extends TimelineKey
-
-case class TopicsPickerTimeline(topicId: Option[String]) extends TimelineKey
-
-case class NotInterestedTopicsMeTimeline() extends TimelineKey
-
-case class FollowedTopicsMeTimeline() extends TimelineKey
-
-case class FollowedTopicsOtherTimeline(userId: Long) extends TimelineKey
-
-case class NuxUserRecommendationsTimeline() extends TimelineKey
-
-case class NuxForYouCategoryUserRecommendationsTimeline() extends TimelineKey
-
-case class NuxPymkCategoryUserRecommendationsTimeline() extends TimelineKey
-
-case class NuxGeoCategoryUserRecommendationsTimeline() extends TimelineKey
-
-case class NuxSingleInterestCategoryUserRecommendationsTimeline(topicId: Option[String])
- extends TimelineKey
-
-case class ShoppingHomeTimeline() extends TimelineKey
-
-case class ForYouExploreMixerTimeline() extends TimelineKey
-
-case class TrendingExploreMixerTimeline() extends TimelineKey
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala
deleted file mode 100644
index 3ef6e3851..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-sealed trait TopicPageHeaderDisplayType
-
-case object BasicTopicPageHeaderDisplayType extends TopicPageHeaderDisplayType
-case object PersonalizedTopicPageHeaderDisplayType extends TopicPageHeaderDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala
deleted file mode 100644
index ce6599028..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urp
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-case class TopicPageHeaderFacepile(
- userIds: Seq[Long],
- facepileUrl: Option[Url] = None)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD
deleted file mode 100644
index 683520b2c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "util/util-core:util-core-util",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module",
- "util/util-core:util-core-util",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala
deleted file mode 100644
index 568fa103f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-trait Cover extends TimelineItem
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala
deleted file mode 100644
index 53838658b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import scala.util.matching.Regex
-
-/**
- * Entry Identifiers (commonly entry ids) are a type of identifier used in URT to identify
- * unique timeline entries - tweets, users, modules, etc.
- *
- * Entry Identifiers are formed from two parts - a namespace (EntryNamespace) and an underlying
- * id.
- *
- * A Entry Namespace is restricted to:
- * - 3 to 60 characters to ensure reasonable length
- * - a-z and dashes (kebab-case)
- * - Examples include "user" and "tweet"
- *
- * When specific entries identifiers are created, they will be appended with a dash and their
- * own id, like user-12 or tweet-20
- */
-
-trait HasEntryNamespace {
- val entryNamespace: EntryNamespace
-}
-
-// sealed abstract case class is basically a scala 2.12 opaque type -
-// you can only create them via the factory method on the companion
-// allowing us to enforce validation
-sealed abstract case class EntryNamespace(override val toString: String)
-
-object EntryNamespace {
- val AllowedCharacters: Regex = "[a-z-]+".r // Allows for kebab-case
-
- def apply(str: String): EntryNamespace = {
- val isValid = str match {
- case n if n.length < 3 =>
- false
- case n if n.length > 60 =>
- false
- case AllowedCharacters() =>
- true
- case _ =>
- false
- }
-
- if (isValid)
- new EntryNamespace(str) {}
- else
- throw new IllegalArgumentException(s"Illegal EntryNamespace: $str")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala
deleted file mode 100644
index 6008172c5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait HasEntryIdentifier extends UniversalNoun[Any] with HasEntryNamespace {
- // Distinctly identifies this entry and must be unique relative to other entries within a response
- lazy val entryIdentifier: String = s"$entryNamespace-$id"
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala
deleted file mode 100644
index e20c75131..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.util.Time
-
-trait HasExpirationTime {
- def expirationTime: Option[Time] = None
-
- final def expirationTimeInMillis: Option[Long] = expirationTime.map(_.inMillis)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala
deleted file mode 100644
index e3a9f6d55..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-trait HasSortIndex { timelineEntry: TimelineEntry =>
- def sortIndex: Option[Long]
-
- def withSortIndex(sortIndex: Long): TimelineEntry
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala
deleted file mode 100644
index c1d612f3d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-
-case class ModuleItemTreeDisplay(
- parentModuleEntryItemId: Option[String],
- indentFromParent: Option[Boolean],
- displayType: Option[ModuleDisplayType],
- isAnchorChild: Option[Boolean])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala
deleted file mode 100644
index 412e6aa67..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import metadata.Url
-
-case class ReaderModeConfig(isReaderModeAvailable: Boolean, landingUrl: Url)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala
deleted file mode 100644
index 602af7498..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert.ShowAlertEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.util.Duration
-
-/**
- * Domain model for the URT ShowAlert [[https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/ShowAlert.html]]
- *
- * @note the text field (id: 2) has been deliberately excluded as it's been deprecated since 2018. Use RichText instead.
- */
-case class ShowAlert(
- override val id: String,
- override val sortIndex: Option[Long],
- alertType: ShowAlertType,
- triggerDelay: Option[Duration],
- displayDuration: Option[Duration],
- clientEventInfo: Option[ClientEventInfo],
- collapseDelay: Option[Duration],
- userIds: Option[Seq[Long]],
- richText: Option[RichText],
- iconDisplayInfo: Option[ShowAlertIconDisplayInfo],
- colorConfig: ShowAlertColorConfiguration,
- displayLocation: ShowAlertDisplayLocation,
- navigationMetadata: Option[ShowAlertNavigationMetadata],
-) extends TimelineItem {
- override val entryNamespace: EntryNamespace = ShowAlertEntryNamespace
-
- // Note that sort index is not used for ShowAlerts, as they are not TimelineEntry and do not have entryId
- override def withSortIndex(newSortIndex: Long): TimelineEntry =
- copy(sortIndex = Some(newSortIndex))
-
- // Not used for ShowAlerts
- override def feedbackActionInfo: Option[FeedbackActionInfo] = None
-}
-
-object ShowAlert {
- val ShowAlertEntryNamespace: EntryNamespace = EntryNamespace("show-alert")
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala
deleted file mode 100644
index 83c46cb9f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-
-case class Timeline(
- id: String,
- instructions: Seq[TimelineInstruction],
- // responseObjects::feedbackActions actions are populated implicitly, see UrtTransportMarshaller
- metadata: Option[TimelineMetadata] = None)
- extends HasMarshalling
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala
deleted file mode 100644
index 70163f3a8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasFeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ReplaceableEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.MarkUnreadableEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior
-
-sealed trait TimelineEntry
- extends HasEntryIdentifier
- with HasSortIndex
- with HasExpirationTime
- with PinnableEntry
- with ReplaceableEntry
- with MarkUnreadableEntry
-
-trait TimelineItem extends TimelineEntry with HasClientEventInfo with HasFeedbackActionInfo
-
-case class ModuleItem(
- item: TimelineItem,
- dispensable: Option[Boolean],
- treeDisplay: Option[ModuleItemTreeDisplay])
-
-case class TimelineModule(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val entryNamespace: EntryNamespace,
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isPinned: Option[Boolean],
- items: Seq[ModuleItem],
- displayType: ModuleDisplayType,
- header: Option[ModuleHeader],
- footer: Option[ModuleFooter],
- metadata: Option[ModuleMetadata],
- showMoreBehavior: Option[ModuleShowMoreBehavior])
- extends TimelineEntry
- with HasClientEventInfo
- with HasFeedbackActionInfo
- with ContainsFeedbackActionInfos {
- override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] = {
- items.map(_.item.feedbackActionInfo) :+ feedbackActionInfo
- }
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
-
-trait TimelineOperation extends TimelineEntry
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala
deleted file mode 100644
index 9b89750cb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasFeedbackActionInfo
-
-sealed trait TimelineInstruction
-
-case class AddEntriesTimelineInstruction(entries: Seq[TimelineEntry])
- extends TimelineInstruction
- with ContainsFeedbackActionInfos {
- override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] =
- entries.flatMap {
- // Order is important, as entries that implement both ContainsFeedbackActionInfos and
- // HasFeedbackActionInfo are expected to include both when implementing ContainsFeedbackActionInfos
- case containsFeedbackActionInfos: ContainsFeedbackActionInfos =>
- containsFeedbackActionInfos.feedbackActionInfos
- case hasFeedbackActionInfo: HasFeedbackActionInfo =>
- Seq(hasFeedbackActionInfo.feedbackActionInfo)
- case _ => Seq.empty
- }
-}
-
-case class ReplaceEntryTimelineInstruction(entry: TimelineEntry)
- extends TimelineInstruction
- with ContainsFeedbackActionInfos {
- override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] =
- entry match {
- // Order is important, as entries that implement both ContainsFeedbackActionInfos and
- // HasFeedbackActionInfo are expected to include both when implementing ContainsFeedbackActionInfos
- case containsFeedbackActionInfos: ContainsFeedbackActionInfos =>
- containsFeedbackActionInfos.feedbackActionInfos
- case hasFeedbackActionInfo: HasFeedbackActionInfo =>
- Seq(hasFeedbackActionInfo.feedbackActionInfo)
- case _ => Seq.empty
- }
-}
-
-case class AddToModuleTimelineInstruction(
- moduleItems: Seq[ModuleItem],
- moduleEntryId: String,
- moduleItemEntryId: Option[String],
- prepend: Option[Boolean])
- extends TimelineInstruction
- with ContainsFeedbackActionInfos {
- override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] =
- moduleItems.map(_.item.feedbackActionInfo)
-}
-
-case class PinEntryTimelineInstruction(entry: TimelineEntry) extends TimelineInstruction
-
-case class MarkEntriesUnreadInstruction(entryIds: Seq[String]) extends TimelineInstruction
-
-case class ClearCacheTimelineInstruction() extends TimelineInstruction
-
-sealed trait TimelineTerminationDirection
-case object TopTermination extends TimelineTerminationDirection
-case object BottomTermination extends TimelineTerminationDirection
-case object TopAndBottomTermination extends TimelineTerminationDirection
-case class TerminateTimelineInstruction(terminateTimelineDirection: TimelineTerminationDirection)
- extends TimelineInstruction
-
-case class ShowCoverInstruction(cover: Cover) extends TimelineInstruction
-
-case class ShowAlertInstruction(showAlert: ShowAlert) extends TimelineInstruction
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala
deleted file mode 100644
index 88b74ea41..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-case class TimelineMetadata(
- title: Option[String],
- scribeConfig: Option[TimelineScribeConfig],
- readerModeConfig: Option[ReaderModeConfig] = None)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala
deleted file mode 100644
index 6a7c46bbc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt
-
-case class TimelineScribeConfig(
- page: Option[String],
- section: Option[String],
- entityToken: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD
deleted file mode 100644
index d5a4881bd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "util/util-core:scala",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- "util/util-core:scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala
deleted file mode 100644
index e8378270d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor
-
-case class ShowAlertColorConfiguration(
- background: RosettaColor,
- text: RosettaColor,
- border: Option[RosettaColor],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala
deleted file mode 100644
index adf797f9b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-sealed trait ShowAlertDisplayLocation
-case object Top extends ShowAlertDisplayLocation
-case object Bottom extends ShowAlertDisplayLocation
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala
deleted file mode 100644
index 0405ca0ba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-sealed trait ShowAlertIcon
-case object UpArrow extends ShowAlertIcon
-case object DownArrow extends ShowAlertIcon
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala
deleted file mode 100644
index e55498c10..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor
-
-case class ShowAlertIconDisplayInfo(icon: ShowAlertIcon, tint: RosettaColor)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala
deleted file mode 100644
index 5cef1453f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-case class ShowAlertNavigationMetadata(navigateToEntryId: String)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala
deleted file mode 100644
index 191ebed40..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.alert
-
-sealed trait ShowAlertType
-case object NewTweets extends ShowAlertType
-case object Navigate extends ShowAlertType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD
deleted file mode 100644
index 5e528fdc8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala
deleted file mode 100644
index 241a9c78e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.button
-
-sealed trait ButtonStyle
-
-case object Default extends ButtonStyle
-case object Primary extends ButtonStyle
-case object Secondary extends ButtonStyle
-case object Text extends ButtonStyle
-case object Destructive extends ButtonStyle
-case object Neutral extends ButtonStyle
-case object DestructiveSecondary extends ButtonStyle
-case object DestructiveText extends ButtonStyle
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala
deleted file mode 100644
index 9820c52ab..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.button
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-sealed trait CtaButton
-
-case class TextCtaButton(buttonText: String, url: Url) extends CtaButton
-
-case class IconCtaButton(buttonIcon: HorizonIcon, accessibilityLabel: String, url: Url)
- extends CtaButton
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD
deleted file mode 100644
index c9ed8c7eb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD
+++ /dev/null
@@ -1,8 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala
deleted file mode 100644
index 6dc9f1869..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.color
-
-case class Color(
- red: Short,
- green: Short,
- blue: Short,
- opacity: Option[Short])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala
deleted file mode 100644
index 36486ee43..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.color
-
-case class ColorPalette(
- rgb: Color,
- percentage: Double)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala
deleted file mode 100644
index cbc36d9bb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.color
-
-sealed trait RosettaColor
-
-case object WhiteRosettaColor extends RosettaColor
-case object BlackRosettaColor extends RosettaColor
-case object ClearRosettaColor extends RosettaColor
-
-case object TextBlackRosettaColor extends RosettaColor
-case object TextBlueRosettaColor extends RosettaColor
-
-case object DeepGrayRosettaColor extends RosettaColor
-case object MediumGrayRosettaColor extends RosettaColor
-case object LightGrayRosettaColor extends RosettaColor
-case object FadedGrayRosettaColor extends RosettaColor
-case object FaintGrayRosettaColor extends RosettaColor
-
-case object DeepOrangeRosettaColor extends RosettaColor
-case object MediumOrangeRosettaColor extends RosettaColor
-case object LightOrangeRosettaColor extends RosettaColor
-case object FadedOrangeRosettaColor extends RosettaColor
-
-case object DeepYellowRosettaColor extends RosettaColor
-case object MediumYellowRosettaColor extends RosettaColor
-case object LightYellowRosettaColor extends RosettaColor
-case object FadedYellowRosettaColor extends RosettaColor
-
-case object DeepGreenRosettaColor extends RosettaColor
-case object MediumGreenRosettaColor extends RosettaColor
-case object LightGreenRosettaColor extends RosettaColor
-case object FadedGreenRosettaColor extends RosettaColor
-
-case object DeepBlueRosettaColor extends RosettaColor
-case object TwitterBlueRosettaColor extends RosettaColor
-case object LightBlueRosettaColor extends RosettaColor
-case object FadedBlueRosettaColor extends RosettaColor
-case object FaintBlueRosettaColor extends RosettaColor
-
-case object DeepPurpleRosettaColor extends RosettaColor
-case object MediumPurpleRosettaColor extends RosettaColor
-case object LightPurpleRosettaColor extends RosettaColor
-case object FadedPurpleRosettaColor extends RosettaColor
-
-case object DeepRedRosettaColor extends RosettaColor
-case object MediumRedRosettaColor extends RosettaColor
-case object LightRedRosettaColor extends RosettaColor
-case object FadedRedRosettaColor extends RosettaColor
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD
deleted file mode 100644
index b58811811..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala
deleted file mode 100644
index 9936003b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref
-
-case class ContextualTweetRef(
- id: Long,
- hydrationContext: Option[TweetHydrationContext])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala
deleted file mode 100644
index c3dd55a0f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref
-
-sealed trait OuterTweetContext
-
-case class QuoteTweetId(id: Long) extends OuterTweetContext
-case class RetweetId(id: Long) extends OuterTweetContext
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala
deleted file mode 100644
index 9104faf7d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref
-
-import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.SafetyLevel
-
-case class TweetHydrationContext(
- safetyLevelOverride: Option[SafetyLevel],
- outerTweetContext: Option[OuterTweetContext])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD
deleted file mode 100644
index 699f48119..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala
deleted file mode 100644
index 0753432c0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-sealed trait CoverContent
-
-case class FullCoverContent(
- displayType: FullCoverDisplayType,
- primaryText: RichText,
- primaryCoverCta: CoverCta,
- secondaryCoverCta: Option[CoverCta],
- secondaryText: Option[RichText],
- imageVariant: Option[ImageVariant],
- details: Option[RichText],
- dismissInfo: Option[DismissInfo],
- imageDisplayType: Option[ImageDisplayType],
- impressionCallbacks: Option[List[Callback]])
- extends CoverContent
-
-case class HalfCoverContent(
- displayType: HalfCoverDisplayType,
- primaryText: RichText,
- primaryCoverCta: CoverCta,
- secondaryCoverCta: Option[CoverCta],
- secondaryText: Option[RichText],
- impressionCallbacks: Option[List[Callback]],
- dismissible: Option[Boolean],
- coverImage: Option[CoverImage],
- dismissInfo: Option[DismissInfo])
- extends CoverContent
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala
deleted file mode 100644
index 2b4bfe706..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-
-case class CoverCta(
- text: String,
- ctaBehavior: CoverCtaBehavior,
- callbacks: Option[List[Callback]],
- clientEventInfo: Option[ClientEventInfo],
- icon: Option[HorizonIcon],
- buttonStyle: Option[ButtonStyle])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala
deleted file mode 100644
index 07e2d6c84..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-sealed trait CoverCtaBehavior
-
-case class CoverBehaviorNavigate(url: Url) extends CoverCtaBehavior
-case class CoverBehaviorDismiss(feedbackMessage: Option[RichText]) extends CoverCtaBehavior
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala
deleted file mode 100644
index 45d4b702e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-
-case class CoverImage(
- imageVariant: ImageVariant,
- imageDisplayType: ImageDisplayType,
- imageAnimationType: Option[ImageAnimationType])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala
deleted file mode 100644
index 6c0ef1ec0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-sealed trait FullCoverDisplayType
-
-case object CoverFullCoverDisplayType extends FullCoverDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala
deleted file mode 100644
index 2160bc3a7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-sealed trait HalfCoverDisplayType
-
-case object CoverHalfCoverDisplayType extends HalfCoverDisplayType
-case object CenterCoverHalfCoverDisplayType extends HalfCoverDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala
deleted file mode 100644
index 8062d23a6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.cover
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover.FullCoverEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover.HalfCoverEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-
-object HalfCover {
- val HalfCoverEntryNamespace = EntryNamespace("half-cover")
-}
-case class HalfCover(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- content: HalfCoverContent)
- extends Cover {
-
- override val entryNamespace: EntryNamespace = HalfCoverEntryNamespace
-
- // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId
- override def withSortIndex(newSortIndex: Long): TimelineEntry =
- copy(sortIndex = Some(newSortIndex))
-
- // Not used for covers
- override def feedbackActionInfo: Option[FeedbackActionInfo] = None
-}
-
-object FullCover {
- val FullCoverEntryNamespace = EntryNamespace("full-cover")
-}
-case class FullCover(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- content: FullCoverContent)
- extends Cover {
-
- override val entryNamespace: EntryNamespace = FullCoverEntryNamespace
-
- // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId
- override def withSortIndex(newSortIndex: Long): TimelineEntry =
- copy(sortIndex = Some(newSortIndex))
-
- // Not used for covers
- override def feedbackActionInfo: Option[FeedbackActionInfo] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD
deleted file mode 100644
index f2657f7bf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [],
- exports = [],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala
deleted file mode 100644
index dbabdaa46..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.icon
-
-sealed trait HorizonIcon
-
-case object Bookmark extends HorizonIcon
-case object Moment extends HorizonIcon
-case object Debug extends HorizonIcon
-case object Error extends HorizonIcon
-case object Follow extends HorizonIcon
-case object Unfollow extends HorizonIcon
-case object Smile extends HorizonIcon
-case object Frown extends HorizonIcon
-case object Help extends HorizonIcon
-case object Link extends HorizonIcon
-case object Message extends HorizonIcon
-case object No extends HorizonIcon
-case object Outgoing extends HorizonIcon
-case object Pin extends HorizonIcon
-case object Retweet extends HorizonIcon
-case object Speaker extends HorizonIcon
-case object Trashcan extends HorizonIcon
-case object Feedback extends HorizonIcon
-case object FeedbackClose extends HorizonIcon
-case object EyeOff extends HorizonIcon
-case object Moderation extends HorizonIcon
-case object Topic extends HorizonIcon
-case object TopicClose extends HorizonIcon
-case object Flag extends HorizonIcon
-case object TopicFilled extends HorizonIcon
-case object NotificationsFollow extends HorizonIcon
-case object Person extends HorizonIcon
-case object BalloonStroke extends HorizonIcon
-case object Calendar extends HorizonIcon
-case object LocationStroke extends HorizonIcon
-case object PersonStroke extends HorizonIcon
-case object Safety extends HorizonIcon
-case object Logo extends HorizonIcon
-case object SparkleOn extends HorizonIcon
-case object StarRising extends HorizonIcon
-case object CameraVideo extends HorizonIcon
-case object ShoppingClock extends HorizonIcon
-case object ArrowRight extends HorizonIcon
-case object SpeakerOff extends HorizonIcon
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD
deleted file mode 100644
index 1b67082a3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["**/*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala
deleted file mode 100644
index 401c5f879..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article
-
-sealed trait ArticleDisplayType
-
-case object Default extends ArticleDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala
deleted file mode 100644
index 1f892bea3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object ArticleItem {
- val ArticleEntryNamespace = EntryNamespace("article")
-}
-
-case class ArticleItem(
- override val id: Int,
- articleSeedType: ArticleSeedType,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- displayType: Option[ArticleDisplayType],
- socialContext: Option[SocialContext])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = ArticleItem.ArticleEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala
deleted file mode 100644
index c08ce74ec..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article
-
-sealed trait ArticleSeedType
-
-/**
- * Seed UTEG with a user's following list (1st degree network)
- */
-case object FollowingListSeed extends ArticleSeedType
-
-/**
- * Seed UTEG with a user's friends of friends (follow graph + 1) list
- */
-case object FriendsOfFriendsSeed extends ArticleSeedType
-
-/**
- * Seed UTEG with a given lists' members
- */
-case object ListIdSeed extends ArticleSeedType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala
deleted file mode 100644
index a4699ebd9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object AudioSpaceItem {
- val SpaceEntryNamespace = EntryNamespace("audiospace")
-}
-
-case class AudioSpaceItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = AudioSpaceItem.SpaceEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala
deleted file mode 100644
index 4ec0b6216..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.card
-
-sealed trait CardDisplayType
-
-case object HeroDisplayType extends CardDisplayType
-case object CellDisplayType extends CardDisplayType
-case object TweetCardDisplayType extends CardDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala
deleted file mode 100644
index b8ebc0240..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.card
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-object CardItem {
- val CardEntryNamespace = EntryNamespace("card")
-}
-
-case class CardItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- cardUrl: String,
- text: Option[String],
- subtext: Option[String],
- url: Option[Url],
- displayType: Option[CardDisplayType])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = CardItem.CardEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala
deleted file mode 100644
index b77fde3fc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem.CommerceProductGroupEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-
-object CommerceProductGroupItem {
- val CommerceProductGroupEntryNamespace: EntryNamespace = EntryNamespace("commerce-product-group")
-}
-
-case class CommerceProductGroupItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo])
- extends TimelineItem {
-
- val entryNamespace: EntryNamespace = CommerceProductGroupEntryNamespace
- def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala
deleted file mode 100644
index a7f3820bc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem.CommerceProductEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-
-object CommerceProductItem {
- val CommerceProductEntryNamespace: EntryNamespace = EntryNamespace("commerce-product")
-}
-
-case class CommerceProductItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo])
- extends TimelineItem {
-
- val entryNamespace: EntryNamespace = CommerceProductEntryNamespace
- def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala
deleted file mode 100644
index 5fa93a9d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-case class ConversationAnnotation(
- conversationAnnotationType: ConversationAnnotationType,
- header: Option[RichText],
- description: Option[RichText])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala
deleted file mode 100644
index ed8d6573a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation
-
-sealed trait ConversationAnnotationType
-
-case object Political extends ConversationAnnotationType
-case object Large extends ConversationAnnotationType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala
deleted file mode 100644
index 4b6e0b161..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.event
-
-sealed trait EventSummaryDisplayType
-
-case object CellEventSummaryDisplayType extends EventSummaryDisplayType
-case object HeroEventSummaryDisplayType extends EventSummaryDisplayType
-case object CellWithProminentSocialContextEventSummaryDisplayType extends EventSummaryDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala
deleted file mode 100644
index f011d72ab..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.event
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object EventSummaryItem {
- val EventSummaryItemEntryNamespace = EntryNamespace("eventsummary")
-}
-
-case class EventSummaryItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- title: String,
- displayType: EventSummaryDisplayType,
- url: Url,
- image: Option[ImageVariant],
- timeString: Option[String])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace =
- EventSummaryItem.EventSummaryItemEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala
deleted file mode 100644
index ad75952c0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-case class ForwardPivot(
- text: RichText,
- landingUrl: Url,
- displayType: ForwardPivotDisplayType,
- iconImageVariant: Option[ImageVariant],
- stateBadge: Option[Badge],
- subtext: Option[RichText],
- backgroundColorName: Option[RosettaColor],
- engagementNudge: Option[Boolean],
- softInterventionDisplayType: Option[SoftInterventionDisplayType])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala
deleted file mode 100644
index 7c13a05f0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot
-
-sealed trait ForwardPivotDisplayType
-
-case object LiveEvent extends ForwardPivotDisplayType
-case object SoftIntervention extends ForwardPivotDisplayType
-case object CommunityNotes extends ForwardPivotDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala
deleted file mode 100644
index 1c07e95b8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot
-
-sealed trait SoftInterventionDisplayType
-
-case object GetTheLatest extends SoftInterventionDisplayType
-case object StayInformed extends SoftInterventionDisplayType
-case object Misleading extends SoftInterventionDisplayType
-case object GovernmentRequested extends SoftInterventionDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala
deleted file mode 100644
index ce3cebc55..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-case class GenericSummaryAction(
- url: Url,
- clientEventInfo: Option[ClientEventInfo])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala
deleted file mode 100644
index fe1a87749..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-case class GenericSummaryContext(
- text: RichText,
- icon: Option[HorizonIcon])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala
deleted file mode 100644
index b4c15baac..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary
-
-sealed trait GenericSummaryItemDisplayType
-
-case object HeroDisplayType extends GenericSummaryItemDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala
deleted file mode 100644
index 74cc6b1c1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.util.Time
-
-object GenericSummaryItem {
- val GenericSummaryItemNamespace: EntryNamespace = EntryNamespace("genericsummary")
-}
-
-case class GenericSummaryItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- headline: RichText,
- displayType: GenericSummaryItemDisplayType,
- userAttributionIds: Seq[Long],
- media: Option[Media],
- context: Option[GenericSummaryContext],
- timestamp: Option[Time],
- onClickAction: Option[GenericSummaryAction],
- promotedMetadata: Option[PromotedMetadata])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = GenericSummaryItem.GenericSummaryItemNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala
deleted file mode 100644
index 5f9263de5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight
-
-case class HighlightedSection(startIndex: Int, endIndex: Int)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala
deleted file mode 100644
index 63f6d29c9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object IconLabelItem {
- val IconLabelEntryNamespace = EntryNamespace("iconlabel")
-}
-
-case class IconLabelItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- text: RichText,
- icon: Option[HorizonIcon])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = IconLabelItem.IconLabelEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala
deleted file mode 100644
index 3b3a7cedf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.label
-
-sealed trait LabelDisplayType
-
-case object InlineHeaderLabelDisplayType extends LabelDisplayType
-case object OtherRepliesSectionHeaderLabelDisplayType extends LabelDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala
deleted file mode 100644
index 890a9ea92..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.label
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object LabelItem {
- val LabelEntryNamespace = EntryNamespace("label")
-}
-
-case class LabelItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- text: String,
- subtext: Option[String],
- disclosureIndicator: Option[Boolean],
- url: Option[Url],
- displayType: Option[LabelDisplayType])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = LabelItem.LabelEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala
deleted file mode 100644
index 7939a2446..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-
-case class MessageAction(
- dismissOnClick: Boolean,
- url: Option[String],
- clientEventInfo: Option[ClientEventInfo],
- onClickCallbacks: Option[Seq[Callback]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala
deleted file mode 100644
index feeaab391..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-sealed trait MessageActionType
-
-case object FollowAllMessageActionType extends MessageActionType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala
deleted file mode 100644
index b8c9c495f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-sealed trait MessageContent
-
-case class InlinePromptMessageContent(
- headerText: String,
- bodyText: Option[String],
- primaryButtonAction: Option[MessageTextAction],
- secondaryButtonAction: Option[MessageTextAction],
- headerRichText: Option[RichText],
- bodyRichText: Option[RichText],
- socialContext: Option[SocialContext],
- userFacepile: Option[UserFacepile])
- extends MessageContent
-
-case class HeaderImagePromptMessageContent(
- headerImage: MessageImage,
- headerText: Option[String],
- bodyText: Option[String],
- primaryButtonAction: Option[MessageTextAction],
- secondaryButtonAction: Option[MessageTextAction],
- action: Option[MessageAction],
- headerRichText: Option[RichText],
- bodyRichText: Option[RichText])
- extends MessageContent
-
-case class CompactPromptMessageContent(
- headerText: String,
- bodyText: Option[String],
- primaryButtonAction: Option[MessageTextAction],
- secondaryButtonAction: Option[MessageTextAction],
- action: Option[MessageAction],
- headerRichText: Option[RichText],
- bodyRichText: Option[RichText])
- extends MessageContent
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala
deleted file mode 100644
index a8ac940e4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-
-case class MessageImage(
- imageVariants: Set[ImageVariant],
- backgroundColor: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala
deleted file mode 100644
index df8d1cc4e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object MessagePromptItem {
- val MessagePromptEntryNamespace = EntryNamespace("messageprompt")
-}
-
-case class MessagePromptItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isPinned: Option[Boolean],
- content: MessageContent,
- impressionCallbacks: Option[List[Callback]])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace =
- MessagePromptItem.MessagePromptEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala
deleted file mode 100644
index fc1b793f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-case class MessageTextAction(
- text: String,
- action: MessageAction)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala
deleted file mode 100644
index 91757a0fe..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-case class UserFacepile(
- userIds: Seq[Long],
- featuredUserIds: Seq[Long],
- action: Option[MessageTextAction],
- actionType: Option[MessageActionType],
- displaysFeaturingText: Option[Boolean],
- displayType: Option[UserFacepileDisplayType])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala
deleted file mode 100644
index f592ee1ca..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message
-
-sealed trait UserFacepileDisplayType
-
-case object LargeUserFacepileDisplayType extends UserFacepileDisplayType
-case object CompactUserFacepileDisplayType extends UserFacepileDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala
deleted file mode 100644
index de057c0a0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-object MomentAnnotationItem {
- val MomentAnnotationEntryNamespace = EntryNamespace("momentannotation")
-}
-
-/**
- * Represents a MomentAnnotation URT item.
- * This is primarily used by Trends Searth Result Page for displaying Trends Title or Description
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/MomentAnnotation.html
- */
-case class MomentAnnotationItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isPinned: Option[Boolean],
- text: Option[RichText],
- header: Option[RichText],
-) extends TimelineItem {
-
- override val entryNamespace: EntryNamespace =
- MomentAnnotationItem.MomentAnnotationEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala
deleted file mode 100644
index d665c5c94..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-
-/**
- * Represents different types of URT Prompts supported such as the Relevance Prompt.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/PromptContent.html
- */
-sealed trait PromptContent
-
-/**
- * Relevance Prompt is a Yes-No style prompt that can be used for collecting feedback from a User
- * about a part of their timeline.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePrompt.html
- */
-case class RelevancePromptContent(
- title: String,
- confirmation: String,
- isRelevantText: String,
- notRelevantText: String,
- isRelevantCallback: Callback,
- notRelevantCallback: Callback,
- displayType: RelevancePromptDisplayType,
- isRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType],
- notRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType])
- extends PromptContent
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala
deleted file mode 100644
index 59ef60bce..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-
-object PromptItem {
- val PromptEntryNamespace = EntryNamespace("relevanceprompt")
-}
-
-case class PromptItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo] = None,
- content: PromptContent,
- impressionCallbacks: Option[List[Callback]])
- extends TimelineItem {
-
- override val entryNamespace: EntryNamespace = PromptItem.PromptEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala
deleted file mode 100644
index f4c04dd15..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt
-
-/**
- * Represents the different ways to display the Relevance Prompt in a timeline.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePromptDisplayType.html
- */
-sealed trait RelevancePromptDisplayType
-
-case object Normal extends RelevancePromptDisplayType
-case object Compact extends RelevancePromptDisplayType
-case object Large extends RelevancePromptDisplayType
-case object ThumbsUpAndDown extends RelevancePromptDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala
deleted file mode 100644
index a8b6d59a5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback
-
-/**
- * Different kinds of follow-ups after a positive-negative feedback on a prompt button.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePromptFollowUpFeedbackType.html
- */
-sealed trait RelevancePromptFollowUpFeedbackType
-
-case class RelevancePromptFollowUpTextInput(
- context: String,
- textFieldPlaceholder: String,
- sendTextCallback: Callback)
- extends RelevancePromptFollowUpFeedbackType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala
deleted file mode 100644
index a686f1f94..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion
-
-/**
- * Represents the different types of Spelling Suggestion items.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/SpellingActionType.html
- */
-sealed trait SpellingActionType
-
-/**
- * Used when the original query is replaced completed by another query in the backend.
- * Clients use the text 'Searching instead for …' to display this suggestion.
- */
-case object ReplaceSpellingActionType extends SpellingActionType
-
-/**
- * Used when the original query is expanded by a suggestion when performing the search.
- * Clients use the text 'Including results for …' to display this suggestion.
- */
-case object ExpandSpellingActionType extends SpellingActionType
-
-/**
- * Used when the search query is not changed and a suggestion is displayed as an alternative query.
- * Clients use the text 'Did you mean … ?' to display the suggestion.
- */
-case object SuggestSpellingActionType extends SpellingActionType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala
deleted file mode 100644
index 439c2023f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-
-object SpellingItem {
- val SpellingEntryNamespace = EntryNamespace("spelling")
-}
-
-/**
- * Represents a Spelling Suggestion URT item. This is primary used by Search timelines for
- * displaying Spelling correction information.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/Spelling.html
- */
-case class SpellingItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- textResult: TextResult,
- spellingActionType: Option[SpellingActionType],
- originalQuery: Option[String])
- extends TimelineItem {
-
- override val entryNamespace: EntryNamespace = SpellingItem.SpellingEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala
deleted file mode 100644
index b6d0afb8a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection
-
-/**
- * Represents text with hit-highlights used for returning search query suggestions.
- *
- * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/TextResult.html
- */
-case class TextResult(
- text: String,
- hitHighlights: Option[Seq[HighlightedSection]],
- score: Option[Double],
- querySource: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala
deleted file mode 100644
index bd2a5a7d8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread
-
-sealed trait ThreadHeaderContent
-
-case class UserThreadHeader(userId: Long) extends ThreadHeaderContent
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala
deleted file mode 100644
index 074d81ec3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-
-object ThreadHeaderItem {
- val ThreadHeaderEntryNamespace = EntryNamespace("threadheader")
-}
-
-case class ThreadHeaderItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isPinned: Option[Boolean],
- content: ThreadHeaderContent)
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = ThreadHeaderItem.ThreadHeaderEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala
deleted file mode 100644
index 85c212c76..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.button.CtaButton
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-sealed trait TileContent
-
-case class StandardTileContent(
- title: String,
- supportingText: String,
- badge: Option[Badge])
- extends TileContent
-
-case class CallToActionTileContent(
- text: String,
- richText: Option[RichText],
- ctaButton: Option[CtaButton])
- extends TileContent
-
-//todo: Add other TileContent types later
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala
deleted file mode 100644
index 8d6498c69..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TileItem {
- val TileEntryNamespace = EntryNamespace("tile")
-}
-
-case class TileItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- title: String,
- supportingText: String,
- url: Option[Url],
- image: Option[ImageVariant],
- content: TileContent)
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TileItem.TileEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala
deleted file mode 100644
index 1fa166559..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone
-
-sealed trait TombstoneDisplayType
-
-case object TweetUnavailable extends TombstoneDisplayType
-case object DisconnectedRepliesAncestor extends TombstoneDisplayType
-case object DisconnectedRepliesDescendant extends TombstoneDisplayType
-case object Inline extends TombstoneDisplayType
-case object NonCompliant extends TombstoneDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala
deleted file mode 100644
index 12e030af4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText
-
-case class TombstoneInfo(
- text: String,
- richText: Option[RichText],
- richRevealText: Option[RichText])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala
deleted file mode 100644
index 00c053439..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TombstoneItem {
- val TombstoneEntryNamespace = EntryNamespace("tombstone")
-}
-
-case class TombstoneItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- tombstoneDisplayType: TombstoneDisplayType,
- tombstoneInfo: Option[TombstoneInfo],
- tweet: Option[TweetItem])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TombstoneItem.TombstoneEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala
deleted file mode 100644
index ea6941f9b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic
-
-sealed trait TopicDisplayType
-
-case object BasicTopicDisplayType extends TopicDisplayType
-case object PillTopicDisplayType extends TopicDisplayType
-case object NoIconTopicDisplayType extends TopicDisplayType
-case object PillWithoutActionIconDisplayType extends TopicDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala
deleted file mode 100644
index 1774abf40..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic
-
-sealed trait TopicFollowPromptDisplayType
-
-case object IncentiveFocusTopicFollowPromptDisplayType extends TopicFollowPromptDisplayType
-case object TopicFocusTopicFollowPromptDisplayType extends TopicFollowPromptDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala
deleted file mode 100644
index ac9466939..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TopicFollowPromptItem {
- val TopicFollowPromptEntryNamespace = EntryNamespace("topicfollowprompt")
-}
-
-case class TopicFollowPromptItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- topicFollowPromptDisplayType: TopicFollowPromptDisplayType,
- followIncentiveTitle: Option[String],
- followIncentiveText: Option[String])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace =
- TopicFollowPromptItem.TopicFollowPromptEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala
deleted file mode 100644
index 6ba979b66..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic
-
-sealed trait TopicFunctionalityType
-
-case object BasicTopicFunctionalityType extends TopicFunctionalityType
-case object PivotTopicFunctionalityType extends TopicFunctionalityType
-case object RecommendationTopicFunctionalityType extends TopicFunctionalityType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala
deleted file mode 100644
index bd2467abd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TopicItem {
- val TopicEntryNamespace = EntryNamespace("topic")
-}
-
-case class TopicItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- topicFunctionalityType: Option[TopicFunctionalityType],
- topicDisplayType: Option[TopicDisplayType])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TopicItem.TopicEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala
deleted file mode 100644
index 86e7fac48..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-
-object TrendItem {
- val TrendItemEntryNamespace = EntryNamespace("trend")
-}
-
-case class GroupedTrend(trendName: String, url: Url)
-
-case class TrendItem(
- override val id: String,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- normalizedTrendName: String,
- trendName: String,
- url: Url,
- description: Option[String],
- metaDescription: Option[String],
- tweetCount: Option[Int],
- domainContext: Option[String],
- promotedMetadata: Option[PromotedMetadata],
- groupedTrends: Option[Seq[GroupedTrend]])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TrendItem.TrendItemEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala
deleted file mode 100644
index 168dd47a9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet
-
-case class TimelinesScoreInfo(score: Double)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala
deleted file mode 100644
index d54512f6a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet
-
-sealed trait TweetDisplayType
-
-case object Tweet extends TweetDisplayType
-case object TweetFollowOnly extends TweetDisplayType
-case object Media extends TweetDisplayType
-case object MomentTimelineTweet extends TweetDisplayType
-case object EmphasizedPromotedTweet extends TweetDisplayType
-case object QuotedTweet extends TweetDisplayType
-case object SelfThread extends TweetDisplayType
-case object CompactPromotedTweet extends TweetDisplayType
-case object TweetWithoutCard extends TweetDisplayType
-case object ReaderModeRoot extends TweetDisplayType
-case object ReaderMode extends TweetDisplayType
-case object CondensedTweet extends TweetDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala
deleted file mode 100644
index e2c1caa4f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection
-
-case class TweetHighlights(
- textHighlights: Option[List[HighlightedSection]],
- cardTitleHighlights: Option[List[HighlightedSection]],
- cardDescriptionHighlights: Option[List[HighlightedSection]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala
deleted file mode 100644
index 15690bd2d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot
-import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-object TweetItem {
- val TweetEntryNamespace = EntryNamespace("tweet")
- val PromotedTweetEntryNamespace = EntryNamespace("promoted-tweet")
-}
-
-case class TweetItem(
- override val id: Long,
- override val entryNamespace: EntryNamespace,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isPinned: Option[Boolean],
- override val entryIdToReplace: Option[String],
- socialContext: Option[SocialContext],
- highlights: Option[TweetHighlights],
- displayType: TweetDisplayType,
- innerTombstoneInfo: Option[TombstoneInfo],
- timelinesScoreInfo: Option[TimelinesScoreInfo],
- hasModeratedReplies: Option[Boolean],
- forwardPivot: Option[ForwardPivot],
- innerForwardPivot: Option[ForwardPivot],
- promotedMetadata: Option[PromotedMetadata],
- conversationAnnotation: Option[ConversationAnnotation],
- contextualTweetRef: Option[ContextualTweetRef],
- prerollMetadata: Option[PrerollMetadata],
- replyBadge: Option[Badge],
- destination: Option[Url])
- extends TimelineItem {
-
- /**
- * Promoted tweets need to include the impression ID in the entry ID since some clients have
- * client-side logic that deduplicates ads impression callbacks based on a combination of the
- * tweet and impression IDs. Not including the impression ID will lead to over deduplication.
- */
- override lazy val entryIdentifier: String = promotedMetadata
- .map { metadata =>
- val impressionId = metadata.impressionString match {
- case Some(impressionString) if impressionString.nonEmpty => impressionString
- case _ => throw new IllegalStateException(s"Promoted Tweet $id missing impression ID")
- }
- s"$entryNamespace-$id-$impressionId"
- }.getOrElse(s"$entryNamespace-$id")
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala
deleted file mode 100644
index a477bb239..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer
-
-sealed trait TweetComposerDisplayType
-
-case object TweetComposerSelfThread extends TweetComposerDisplayType
-case object Reply extends TweetComposerDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala
deleted file mode 100644
index 4340c5328..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TweetComposerItem {
- val TweetComposerEntryNameSpace = EntryNamespace("tweetcomposer")
-}
-
-case class TweetComposerItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- displayType: TweetComposerDisplayType,
- text: String,
- url: Url)
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TweetComposerItem.TweetComposerEntryNameSpace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala
deleted file mode 100644
index b80e8cc05..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list
-
-sealed trait TwitterListDisplayType
-
-case object List extends TwitterListDisplayType
-case object ListTile extends TwitterListDisplayType
-case object ListWithPin extends TwitterListDisplayType
-case object ListWithSubscribe extends TwitterListDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala
deleted file mode 100644
index c585b145b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-object TwitterListItem {
- val ListEntryNamespace = EntryNamespace("list")
-}
-
-case class TwitterListItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- displayType: Option[TwitterListDisplayType])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = TwitterListItem.ListEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala
deleted file mode 100644
index a73e76d54..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user
-
-sealed trait UserDisplayType
-
-case object User extends UserDisplayType
-case object UserDetailed extends UserDisplayType
-case object PendingFollowUser extends UserDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala
deleted file mode 100644
index 5bb1209c9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata
-
-object UserItem {
- val UserEntryNamespace: EntryNamespace = EntryNamespace("user")
-}
-
-case class UserItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- override val isMarkUnread: Option[Boolean],
- displayType: UserDisplayType,
- promotedMetadata: Option[PromotedMetadata],
- socialContext: Option[SocialContext],
- reactiveTriggers: Option[UserReactiveTriggers],
- enableReactiveBlending: Option[Boolean])
- extends TimelineItem {
- override val entryNamespace: EntryNamespace = UserItem.UserEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala
deleted file mode 100644
index 87bdda4b9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.TimelineReaction
-
-case class UserReactiveTriggers(onFollow: Option[TimelineReaction])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala
deleted file mode 100644
index d96416a1f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-sealed trait VerticalGridItem extends TimelineItem
-
-object VerticalGridItemTopicTile {
- val VerticalGridItemTopicTileEntryNamespace = EntryNamespace("verticalgriditemtopictile")
-}
-
-case class VerticalGridItemTopicTile(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- style: Option[VerticalGridItemTileStyle],
- functionalityType: Option[VerticalGridItemTopicFunctionalityType],
- url: Option[Url])
- extends VerticalGridItem {
- override val entryNamespace: EntryNamespace =
- VerticalGridItemTopicTile.VerticalGridItemTopicTileEntryNamespace
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala
deleted file mode 100644
index 869322ebc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item
-
-sealed trait VerticalGridItemTileStyle
-
-case object SingleStateDefaultVerticalGridItemTileStyle extends VerticalGridItemTileStyle
-case object DoubleStateDefaultVerticalGridItemTileStyle extends VerticalGridItemTileStyle
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala
deleted file mode 100644
index 961aadc27..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item
-
-sealed trait VerticalGridItemTopicFunctionalityType
-
-case object PivotVerticalGridItemTopicFunctionalityType
- extends VerticalGridItemTopicFunctionalityType
-case object RecommendationVerticalGridItemTopicFunctionalityType
- extends VerticalGridItemTopicFunctionalityType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala
deleted file mode 100644
index f81020c8b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.media
-
-case class AspectRatio(
- numerator: Short,
- denominator: Short)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD
deleted file mode 100644
index ae81ac4e2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala
deleted file mode 100644
index 82fcb3e9f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.media
-
-case class Media(
- mediaEntity: Option[MediaEntity],
- mediaKey: Option[MediaKey],
- imagePossibleCropping: Option[List[Rect]],
- aspectRatio: Option[AspectRatio])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala
deleted file mode 100644
index 5def14bc6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.media
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-
-sealed trait MediaEntity
-
-case class TweetMedia(
- tweetId: Long,
- momentId: Option[Long])
- extends MediaEntity
-
-case class BroadcastId(id: String) extends MediaEntity
-
-case class Image(image: ImageVariant) extends MediaEntity
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala
deleted file mode 100644
index 191a5d3f4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.media
-
-case class MediaKey(
- id: Long,
- category: Int)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala
deleted file mode 100644
index ecd3d2c82..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.media
-
-case class Rect(
- left: Int,
- top: Int,
- width: Int,
- height: Int)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala
deleted file mode 100644
index 135a5d2ad..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class ArticleDetails(
- articlePosition: Int,
- shareCount: Int)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD
deleted file mode 100644
index 669bbc52b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala
deleted file mode 100644
index 1c12ce262..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor
-
-case class Badge(
- text: Option[String],
- textColorName: Option[RosettaColor],
- backgroundColorName: Option[RosettaColor])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala
deleted file mode 100644
index 9ab8c082c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class Callback(endpoint: String)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala
deleted file mode 100644
index f78750ca0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-trait HasClientEventInfo {
- def clientEventInfo: Option[ClientEventInfo]
-}
-
-/**
- * Information used to build Client Events
- * @see [[http://go/client-events]]
- */
-case class ClientEventInfo(
- component: Option[String],
- element: Option[String],
- details: Option[ClientEventDetails],
- action: Option[String],
- entityToken: Option[String])
-
-/**
- * Additional client events fields
- *
- * @note if a field from [[http://go/client_app.thrift]] is needed but is not here
- * contact the `#product-mixer` team to have it added.
- */
-case class ClientEventDetails(
- conversationDetails: Option[ConversationDetails],
- timelinesDetails: Option[TimelinesDetails],
- articleDetails: Option[ArticleDetails],
- liveEventDetails: Option[LiveEventDetails],
- commerceDetails: Option[CommerceDetails])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala
deleted file mode 100644
index 86cc9dc15..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class CommerceDetails(
- dropId: Option[Long],
- shopV2Id: Option[Long],
- productKey: Option[Long],
- merchantId: Option[Long],
- productIndex: Option[Int])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala
deleted file mode 100644
index 66aed65f5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait ConfirmationDisplayType
-
-case object Inline extends ConfirmationDisplayType
-case object BottomSheet extends ConfirmationDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala
deleted file mode 100644
index be7a48935..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class ConversationDetails(conversationSection: Option[ConversationSection])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala
deleted file mode 100644
index 0ba7a68b4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait ConversationSection
-
-case object HighQuality extends ConversationSection
-case object LowQuality extends ConversationSection
-case object AbusiveQuality extends ConversationSection
-case object RelatedTweet extends ConversationSection
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala
deleted file mode 100644
index 3f11122ad..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class DismissInfo(callbacks: Option[Seq[Callback]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala
deleted file mode 100644
index 753ae9ca8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-
-case class FeedbackAction(
- feedbackType: FeedbackType,
- prompt: Option[String],
- confirmation: Option[String],
- childFeedbackActions: Option[Seq[ChildFeedbackAction]],
- feedbackUrl: Option[String],
- hasUndoAction: Option[Boolean],
- confirmationDisplayType: Option[ConfirmationDisplayType],
- clientEventInfo: Option[ClientEventInfo],
- icon: Option[HorizonIcon],
- richBehavior: Option[RichFeedbackBehavior],
- subprompt: Option[String],
- encodedFeedbackRequest: Option[String])
-
-case class ChildFeedbackAction(
- feedbackType: FeedbackType,
- prompt: Option[String],
- confirmation: Option[String],
- feedbackUrl: Option[String],
- hasUndoAction: Option[Boolean],
- confirmationDisplayType: Option[ConfirmationDisplayType],
- clientEventInfo: Option[ClientEventInfo],
- icon: Option[HorizonIcon],
- richBehavior: Option[RichFeedbackBehavior],
- subprompt: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala
deleted file mode 100644
index 1eebf6cf5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-trait HasFeedbackActionInfo {
- def feedbackActionInfo: Option[FeedbackActionInfo]
-}
-
-trait ContainsFeedbackActionInfos {
- def feedbackActionInfos: Seq[Option[FeedbackActionInfo]]
-}
-
-case class FeedbackActionInfo(
- feedbackActions: Seq[FeedbackAction],
- feedbackMetadata: Option[String],
- displayContext: Option[FeedbackDisplayContext],
- clientEventInfo: Option[ClientEventInfo])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala
deleted file mode 100644
index e257b909b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-trait HasFeedbackInfo {
- def feedbackInfo: Option[FeedbackInfo]
-}
-
-case class FeedbackDisplayContext(reason: String)
-
-case class FeedbackInfo(
- feedbackKeys: Seq[String],
- feedbackMetadata: Option[String],
- displayContext: Option[FeedbackDisplayContext],
- clientEventInfo: Option[ClientEventInfo])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala
deleted file mode 100644
index df2c274b5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait FeedbackType
-
-case object Dismiss extends FeedbackType
-case object SeeFewer extends FeedbackType
-case object DontLike extends FeedbackType
-case object NotRelevant extends FeedbackType
-case object SeeMore extends FeedbackType
-case object NotCredible extends FeedbackType
-case object GiveFeedback extends FeedbackType
-case object NotRecent extends FeedbackType
-case object UnfollowEntity extends FeedbackType
-case object Relevant extends FeedbackType
-case object Moderate extends FeedbackType
-case object RichBehavior extends FeedbackType
-case object NotAboutTopic extends FeedbackType
-case object Generic extends FeedbackType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala
deleted file mode 100644
index 143af16c9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait ImageAnimationType
-
-case object Bounce extends ImageAnimationType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala
deleted file mode 100644
index 79008df60..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait ImageDisplayType
-
-case object Icon extends ImageDisplayType
-case object FullWidth extends ImageDisplayType
-case object IconSmall extends ImageDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala
deleted file mode 100644
index 08b57a66e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ColorPalette
-
-case class ImageVariant(
- url: String,
- width: Int,
- height: Int,
- palette: Option[List[ColorPalette]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala
deleted file mode 100644
index 931c98bba..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class LiveEventDetails(eventId: Option[Long])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala
deleted file mode 100644
index f26eed533..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-// Track unread entries for the MarkUnread URT instruction.
-trait MarkUnreadableEntry {
- def isMarkUnread: Option[Boolean] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala
deleted file mode 100644
index f99565d8f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-trait PinnableEntry {
- def isPinned: Option[Boolean] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala
deleted file mode 100644
index 2fc7442b5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-trait ReplaceableEntry {
- def entryIdToReplace: Option[String] = None
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala
deleted file mode 100644
index 83a056bf7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait ReplyPinState
-
-object PinnedReplyPinState extends ReplyPinState
-object PinnableReplyPinState extends ReplyPinState
-object NotPinnableReplyPinState extends ReplyPinState
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala
deleted file mode 100644
index 2ae86471f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait RichFeedbackBehavior
-
-case class RichFeedbackBehaviorReportList(listId: Long, userId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorBlockUser(userId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorToggleFollowTopic(topicId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorToggleFollowTopicV2(topicId: String) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorToggleMuteList(listId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorMarkNotInterestedTopic(topicId: String) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorReplyPinState(replyPinState: ReplyPinState)
- extends RichFeedbackBehavior
-case class RichFeedbackBehaviorToggleMuteUser(userId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorToggleFollowUser(userId: Long) extends RichFeedbackBehavior
-case class RichFeedbackBehaviorReportTweet(entryId: Long) extends RichFeedbackBehavior
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala
deleted file mode 100644
index ed6fc2652..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-sealed trait SocialContext
-
-trait HasSocialContext {
- def socialContext: Option[SocialContext]
-}
-
-sealed trait GeneralContextType
-case object LikeGeneralContextType extends GeneralContextType
-case object FollowGeneralContextType extends GeneralContextType
-case object MomentGeneralContextType extends GeneralContextType
-case object ReplyGeneralContextType extends GeneralContextType
-case object ConversationGeneralContextType extends GeneralContextType
-case object PinGeneralContextType extends GeneralContextType
-case object TextOnlyGeneralContextType extends GeneralContextType
-case object FacePileGeneralContextType extends GeneralContextType
-case object MegaPhoneGeneralContextType extends GeneralContextType
-case object BirdGeneralContextType extends GeneralContextType
-case object FeedbackGeneralContextType extends GeneralContextType
-case object TopicGeneralContextType extends GeneralContextType
-case object ListGeneralContextType extends GeneralContextType
-case object RetweetGeneralContextType extends GeneralContextType
-case object LocationGeneralContextType extends GeneralContextType
-case object CommunityGeneralContextType extends GeneralContextType
-case object NewUserGeneralContextType extends GeneralContextType
-case object SmartblockExpirationGeneralContextType extends GeneralContextType
-case object TrendingGeneralContextType extends GeneralContextType
-case object SparkleGeneralContextType extends GeneralContextType
-case object SpacesGeneralContextType extends GeneralContextType
-case object ReplyPinGeneralContextType extends GeneralContextType
-
-case class GeneralContext(
- contextType: GeneralContextType,
- text: String,
- url: Option[String],
- contextImageUrls: Option[List[String]],
- landingUrl: Option[Url])
- extends SocialContext
-
-sealed trait TopicContextFunctionalityType
-case object BasicTopicContextFunctionalityType extends TopicContextFunctionalityType
-case object RecommendationTopicContextFunctionalityType extends TopicContextFunctionalityType
-case object RecWithEducationTopicContextFunctionalityType extends TopicContextFunctionalityType
-
-case class TopicContext(
- topicId: String,
- functionalityType: Option[TopicContextFunctionalityType])
- extends SocialContext
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala
deleted file mode 100644
index 57f6fd58a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-case class TimelinesDetails(
- injectionType: Option[String],
- controllerData: Option[String],
- sourceData: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala
deleted file mode 100644
index 112b278d7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject
-
-sealed trait UrlType
-case object ExternalUrl extends UrlType
-case object DeepLink extends UrlType
-case object UrtEndpoint extends UrlType
-
-case class UrtEndpointOptions(
- requestParams: Option[Map[String, String]],
- title: Option[String],
- cacheId: Option[String],
- subtitle: Option[String])
-
-case class Url(urlType: UrlType, url: String, urtEndpointOptions: Option[UrtEndpointOptions] = None)
- extends ReferenceObject
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD
deleted file mode 100644
index 25898763c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala
deleted file mode 100644
index babf20ea6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.operation
-
-case class CursorDisplayTreatment(
- actionText: Option[String],
- labelText: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala
deleted file mode 100644
index 0ea733c08..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation.CursorEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem
-
-/**
- * CursorItem should only be used for Module cursors
- * For timeline cursors, see
- * [[com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation]]
- */
-case class CursorItem(
- override val id: Long,
- override val sortIndex: Option[Long],
- override val clientEventInfo: Option[ClientEventInfo],
- override val feedbackActionInfo: Option[FeedbackActionInfo],
- value: String,
- cursorType: CursorType,
- displayTreatment: Option[CursorDisplayTreatment])
- extends TimelineItem {
-
- override val entryNamespace: EntryNamespace = CursorEntryNamespace
-
- override lazy val entryIdentifier: String =
- s"$entryNamespace-${cursorType.entryNamespace}-$id"
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala
deleted file mode 100644
index 9bcf0a1d1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation.CursorEntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry
-import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation
-
-object CursorOperation {
- val CursorEntryNamespace = EntryNamespace("cursor")
-
- private def entryIdentifier(cursorType: CursorType, identifier: Long): String =
- s"$CursorEntryNamespace-${cursorType.entryNamespace.toString}-$identifier"
-}
-
-case class CursorOperation(
- override val id: Long,
- override val sortIndex: Option[Long],
- value: String,
- cursorType: CursorType,
- displayTreatment: Option[CursorDisplayTreatment],
- idToReplace: Option[Long])
- extends TimelineOperation {
- override val entryNamespace: EntryNamespace = CursorEntryNamespace
-
- override lazy val entryIdentifier: String = CursorOperation.entryIdentifier(cursorType, id)
-
- override def entryIdToReplace: Option[String] =
- idToReplace.map(CursorOperation.entryIdentifier(cursorType, _))
-
- override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala
deleted file mode 100644
index 298a24052..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.operation
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace
-import com.twitter.product_mixer.core.model.marshalling.response.urt.HasEntryNamespace
-
-sealed trait CursorType extends HasEntryNamespace
-
-case object TopCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("top")
-}
-case object BottomCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("bottom")
-}
-case object GapCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("gap")
-}
-case object PivotCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("pivot")
-}
-case object SubBranchCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("subbranch")
-}
-case object ShowMoreCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("showmore")
-}
-case object ShowMoreThreadsCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("showmorethreads")
-}
-case object ShowMoreThreadsPromptCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("showmorethreadsprompt")
-}
-case object SecondRepliesSectionCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("secondrepliessection")
-}
-case object ThirdRepliesSectionCursor extends CursorType {
- override val entryNamespace: EntryNamespace = EntryNamespace("thirdrepliessection")
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala
deleted file mode 100644
index 756c2ceb3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class AdMetadataContainer(
- removePromotedAttributionForPreroll: Option[Boolean],
- sponsorshipCandidate: Option[String],
- sponsorshipOrganization: Option[String],
- sponsorshipOrganizationWebsite: Option[String],
- sponsorshipType: Option[SponsorshipType],
- disclaimerType: Option[DisclaimerType],
- skAdNetworkDataList: Option[Seq[SkAdNetworkData]],
- unifiedCardOverride: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD
deleted file mode 100644
index 7ef37be56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ],
- exports = [
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala
deleted file mode 100644
index 4cabb4855..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class CallToAction(
- callToActionType: Option[String],
- url: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala
deleted file mode 100644
index a29da2634..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-import scala.collection.Map
-
-case class ClickTrackingInfo(
- urlParams: Map[String, String],
- urlOverride: Option[String],
- urlOverrideType: Option[UrlOverrideType])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala
deleted file mode 100644
index 72508ccd4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-sealed trait DisclaimerType
-
-object DisclaimerPolitical extends DisclaimerType
-object DisclaimerIssue extends DisclaimerType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala
deleted file mode 100644
index 624c871b3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-sealed trait DisclosureType
-
-case object NoDisclosure extends DisclosureType
-case object Political extends DisclosureType
-case object Earned extends DisclosureType
-case object Issue extends DisclosureType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala
deleted file mode 100644
index c4a7c3306..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-sealed trait DynamicPrerollType
-
-object Amplify extends DynamicPrerollType
-object Marketplace extends DynamicPrerollType
-object LiveTvEvent extends DynamicPrerollType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala
deleted file mode 100644
index 5e2eb001d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class MediaInfo(
- uuid: Option[String],
- publisherId: Option[Long],
- callToAction: Option[CallToAction],
- durationMillis: Option[Int],
- videoVariants: Option[Seq[VideoVariant]],
- advertiserName: Option[String],
- renderAdByAdvertiserName: Option[Boolean],
- advertiserProfileImageUrl: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala
deleted file mode 100644
index 51e83da8b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class Preroll(
- prerollId: Option[String],
- dynamicPrerollType: Option[DynamicPrerollType],
- mediaInfo: Option[MediaInfo])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala
deleted file mode 100644
index ee7a72940..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class PrerollMetadata(
- preroll: Option[Preroll],
- videoAnalyticsScribePassthrough: Option[String])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala
deleted file mode 100644
index 1fa5ff04a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-/*
- * As per discussion with #revenue-serving on 9/22/2017, `impressionId` should be set from `impressionString`.
- * impressionId often returns None from adserver, as it's been replaced with impressionString.
- *
- * However, Android (at least) crashes without impressionId filled out in the response.
- *
- * So, we've removed `impressionId` from this case class, and our marshaller will set both `impressionId`
- * and `impressionString` in the render thrift from `impressionString`.
- */
-
-case class PromotedMetadata(
- advertiserId: Long,
- disclosureType: Option[DisclosureType],
- experimentValues: Option[Map[String, String]],
- promotedTrendId: Option[Long],
- promotedTrendName: Option[String],
- promotedTrendQueryTerm: Option[String],
- adMetadataContainer: Option[AdMetadataContainer],
- promotedTrendDescription: Option[String],
- impressionString: Option[String],
- clickTrackingInfo: Option[ClickTrackingInfo])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala
deleted file mode 100644
index a5ab45755..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class SkAdNetworkData(
- version: Option[String], // version of the SKAdNetwork protocol
- srcAppId: Option[String], // app showing the ad (Twitter app or app promoting through MOPUB)
- dstAppId: Option[String], // app being promoted
- adNetworkId: Option[String], // the ad-network-id being used
- campaignId: Option[Long], // the sk-campaign-id - different from the Twitter campaign id
- impressionTimeInMillis: Option[Long], // the timestamp of the impression
- nonce: Option[String], // nonce used to generate the signature
- signature: Option[String], // the signed payload
- fidelityType: Option[Long] // th
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala
deleted file mode 100644
index 5594450d5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-sealed trait SponsorshipType
-
-case object DirectSponsorshipType extends SponsorshipType
-case object IndirectSponsorshipType extends SponsorshipType
-case object NoSponsorshipSponsorshipType extends SponsorshipType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala
deleted file mode 100644
index 86730c18d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-sealed trait UrlOverrideType
-
-object UnknownUrlOverrideType extends UrlOverrideType
-object DcmUrlOverrideType extends UrlOverrideType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala
deleted file mode 100644
index c4b56034a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted
-
-case class VideoVariant(
- url: Option[String],
- contentType: Option[String],
- bitrate: Option[Int])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD
deleted file mode 100644
index 7ef37be56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ],
- exports = [
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala
deleted file mode 100644
index 0dd5fe4a8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.reaction
-
-case class TimelineReaction(
- execution: TimelineReactionExecution,
- maxExecutionCount: Option[Short])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala
deleted file mode 100644
index d2785b2cb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.reaction
-
-sealed abstract class TimelineReactionExecution
-
-case class ImmediateTimelineReaction(key: String) extends TimelineReactionExecution
-
-case class RemoteTimelineReaction(
- requestParams: Map[String, String],
- timeoutInSeconds: Option[Short])
- extends TimelineReactionExecution
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD
deleted file mode 100644
index 7ef37be56..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ],
- exports = [
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala
deleted file mode 100644
index 5f4d808a7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext
-
-trait ReferenceObject
-
-case class RichTextUser(id: Long) extends ReferenceObject
-case class RichTextMention(id: Long, screenName: String) extends ReferenceObject
-case class RichTextHashtag(text: String) extends ReferenceObject
-case class RichTextCashtag(text: String) extends ReferenceObject
-case class RichTextList(id: Long, url: String) extends ReferenceObject
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala
deleted file mode 100644
index 8ff4a2788..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext
-
-case class RichText(
- text: String,
- entities: List[RichTextEntity],
- rtl: Option[Boolean],
- alignment: Option[RichTextAlignment])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala
deleted file mode 100644
index fe18486bc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext
-
-sealed trait RichTextAlignment
-
-case object Natural extends RichTextAlignment
-case object Center extends RichTextAlignment
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala
deleted file mode 100644
index a3a577a80..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext
-
-case class RichTextEntity(
- fromIndex: Int,
- toIndex: Int,
- ref: Option[ReferenceObject],
- format: Option[RichTextFormat])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala
deleted file mode 100644
index da8afe13a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext
-
-sealed trait RichTextFormat {
- def name: String
-}
-
-case object Plain extends RichTextFormat {
- override val name: String = "Plain"
-}
-
-case object Strong extends RichTextFormat {
- override val name: String = "Strong"
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala
deleted file mode 100644
index b1f77a489..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-case class AdsMetadata(carouselId: Option[Long])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD
deleted file mode 100644
index bac59b4cb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala
deleted file mode 100644
index f596e1b10..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-case class GridCarouselMetadata(numRows: Option[Int])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala
deleted file mode 100644
index 03826fb33..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-
-case class ModuleConversationMetadata(
- allTweetIds: Option[Seq[Long]],
- socialContext: Option[SocialContext],
- enableDeduplication: Option[Boolean])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala
deleted file mode 100644
index 9b5d3e5a0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-sealed trait ModuleDisplayType
-
-case object Carousel extends ModuleDisplayType
-case object CompactCarousel extends ModuleDisplayType
-case object ConversationTree extends ModuleDisplayType
-case object GridCarousel extends ModuleDisplayType
-case object Vertical extends ModuleDisplayType
-case object VerticalConversation extends ModuleDisplayType
-case object VerticalGrid extends ModuleDisplayType
-case object VerticalWithContextLine extends ModuleDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala
deleted file mode 100644
index 826df3bc0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url
-
-case class ModuleFooter(
- text: String,
- landingUrl: Option[Url])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala
deleted file mode 100644
index 06f7bd14c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant
-import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext
-
-case class ModuleHeader(
- text: String,
- sticky: Option[Boolean],
- icon: Option[HorizonIcon],
- customIcon: Option[ImageVariant],
- socialContext: Option[SocialContext],
- moduleHeaderDisplayType: ModuleHeaderDisplayType)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala
deleted file mode 100644
index 1f0088c4a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-sealed trait ModuleHeaderDisplayType
-
-case object Classic extends ModuleHeaderDisplayType
-case object ContextEmphasis extends ModuleHeaderDisplayType
-case object ClassicNoDivider extends ModuleHeaderDisplayType
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala
deleted file mode 100644
index 5d840f3da..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-object ModuleMetadata {
- def isConversationModule(moduleMetadata: Option[ModuleMetadata]): Boolean =
- moduleMetadata.map(_.conversationMetadata).isDefined
-}
-
-case class ModuleMetadata(
- adsMetadata: Option[AdsMetadata],
- conversationMetadata: Option[ModuleConversationMetadata],
- gridCarouselMetadata: Option[GridCarouselMetadata])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala
deleted file mode 100644
index c7e3ae3f6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module
-
-sealed trait ModuleShowMoreBehavior
-
-case class ModuleShowMoreBehaviorRevealByCount(
- initialItemsCount: Int,
- showMoreItemsCount: Int)
- extends ModuleShowMoreBehavior
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala
deleted file mode 100644
index e695dcede..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.google.inject.Provides
-import com.twitter.abdecider.ABDeciderFactory
-import com.twitter.abdecider.LoggingABDecider
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.logging._
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ScribeABImpressions
-import javax.inject.Singleton
-
-object ABDeciderModule extends TwitterModule {
- private val YmlPath = "/usr/local/config/abdecider/abdecider.yml"
-
- @Provides
- @Singleton
- def provideLoggingABDecider(
- @Flag(ScribeABImpressions) isScribeAbImpressions: Boolean,
- stats: StatsReceiver
- ): LoggingABDecider = {
- val clientEventsHandler: HandlerFactory =
- if (isScribeAbImpressions) {
- QueueingHandler(
- maxQueueSize = 10000,
- handler = ScribeHandler(
- category = "client_event",
- formatter = BareFormatter,
- level = Some(Level.INFO),
- statsReceiver = stats.scope("abdecider"))
- )
- } else { () =>
- NullHandler
- }
-
- val factory = LoggerFactory(
- node = "abdecider",
- level = Some(Level.INFO),
- useParents = false,
- handlers = clientEventsHandler :: Nil
- )
-
- val abDeciderFactory = ABDeciderFactory(
- abDeciderYmlPath = YmlPath,
- scribeLogger = Some(factory()),
- environment = Some("production")
- )
-
- abDeciderFactory.buildWithLogging()
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD
deleted file mode 100644
index 846bbbacc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD
+++ /dev/null
@@ -1,49 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject",
- "3rdparty/jvm/net/codingwell:scala-guice",
- "3rdparty/jvm/org/slf4j:slf4j-api",
- "abdecider",
- "decider",
- "featureswitches/featureswitches-core/src/main/scala/com/twitter/featureswitches/v2/builder",
- "finatra-internal/decider/src/main/scala",
- "finatra-internal/international/src/main/scala/com/twitter/finatra/international/modules",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-thrift-client/src/main/scala",
- "finatra/jackson/src/main/scala/com/twitter/finatra/jackson/modules",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "servo/decider",
- "strato/src/main/scala/com/twitter/strato/client",
- "timelines/src/main/scala/com/twitter/timelines/features/app",
- "util-internal/scribe",
- "util/util-slf4j-api/src/main/scala",
- ],
- exports = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject",
- "3rdparty/jvm/net/codingwell:scala-guice",
- "3rdparty/jvm/org/slf4j:slf4j-api",
- "abdecider",
- "decider",
- "finatra-internal/decider/src/main/scala",
- "finatra-internal/international/src/main/scala/com/twitter/finatra/international/modules",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-thrift-client/src/main/scala",
- "finatra/jackson/src/main/scala/com/twitter/finatra/jackson/modules",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "servo/decider",
- "timelines/src/main/scala/com/twitter/timelines/features/app",
- "util-internal/scribe",
- "util/util-slf4j-api/src/main/scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala
deleted file mode 100644
index c7b1bec0b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.google.inject.Provides
-import com.twitter.decider.Decider
-import com.twitter.inject.TwitterModule
-import com.twitter.product_mixer.core.functional_component.configapi.ConfigBuilder
-import com.twitter.servo.decider.DeciderGateBuilder
-import com.twitter.timelines.configapi.Config
-import javax.inject.Singleton
-
-object ConfigApiModule extends TwitterModule {
-
- @Provides
- @Singleton
- def providesDeciderGateBuilder(decider: Decider): DeciderGateBuilder =
- new DeciderGateBuilder(decider)
-
- @Provides
- @Singleton
- def providesConfig(configBuilder: ConfigBuilder): Config = configBuilder.build()
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala
deleted file mode 100644
index c2f615696..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.google.inject.Provides
-import com.twitter.abdecider.LoggingABDecider
-import com.twitter.featureswitches.v2.FeatureSwitches
-import com.twitter.featureswitches.v2.builder.FeatureSwitchesBuilder
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ConfigRepoLocalPath
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.FeatureSwitchesPath
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.timelines.features.app.ForcibleFeatureValuesModule
-import javax.inject.Singleton
-
-object FeatureSwitchesModule extends TwitterModule with ForcibleFeatureValuesModule {
- private val DefaultConfigRepoPath = "/usr/local/config"
-
- @Provides
- @Singleton
- def providesFeatureSwitches(
- abDecider: LoggingABDecider,
- statsReceiver: StatsReceiver,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- @Flag(ConfigRepoLocalPath) localConfigRepoPath: String,
- @Flag(FeatureSwitchesPath) featuresPath: String
- ): FeatureSwitches = {
- val configRepoPath = if (isServiceLocal) {
- localConfigRepoPath
- } else {
- DefaultConfigRepoPath
- }
-
- val baseBuilder = FeatureSwitchesBuilder
- .createDefault(featuresPath, abDecider, Some(statsReceiver))
- .configRepoAbsPath(configRepoPath)
- .forcedValues(getFeatureSwitchOverrides)
- // Track stats when an experiment impression is made. For example:
- // "experiment_impressions/test_experiment_1234/"
- // "experiment_impressions/test_experiment_1234/control"
- // "experiment_impressions/test_experiment_1234/treatment"
- .experimentImpressionStatsEnabled(true)
- .unitsOfDiversionEnable(true)
-
- val finalBuilder = if (isServiceLocal) {
- baseBuilder
- } else {
- baseBuilder.serviceDetailsFromAurora()
- }
-
- finalBuilder.build()
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala
deleted file mode 100644
index 0332e9819..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.twitter.finatra.thrift.exceptions.ExceptionMapper
-import com.twitter.inject.Logging
-import com.twitter.util.Future
-import javax.inject.Singleton
-import scala.util.control.NonFatal
-
-/**
- * Similar to [[com.twitter.finatra.thrift.internal.exceptions.ThrowableExceptionMapper]]
- *
- * But this one also logs the exceptions.
- */
-@Singleton
-class LoggingThrowableExceptionMapper extends ExceptionMapper[Throwable, Nothing] with Logging {
-
- override def handleException(throwable: Throwable): Future[Nothing] = {
- error("Unhandled Exception", throwable)
-
- throwable match {
- case NonFatal(e) => Future.exception(e)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala
deleted file mode 100644
index 3047135fa..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.twitter.inject.TwitterModule
-import com.twitter.product_mixer.core.service.pipeline_execution_logger.AllowListedPipelineExecutionLogger
-import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger
-
-object PipelineExecutionLoggerModule extends TwitterModule {
-
- override protected def configure(): Unit = {
- bind[PipelineExecutionLogger].to[AllowListedPipelineExecutionLogger]
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala
deleted file mode 100644
index 8c7f98eb8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.twitter.inject.TwitterModule
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule
-import com.twitter.finatra.decider.modules.DeciderModule
-import com.twitter.finatra.international.modules.LanguagesModule
-import com.twitter.product_mixer.core.product.guice.ProductScopeModule
-import com.twitter.finatra.jackson.modules.ScalaObjectMapperModule
-import com.twitter.inject.thrift.modules.ThriftClientIdModule
-
-/**
- * ProductMixerModule provides modules required by all Product Mixer services.
- *
- * @note if your service calls Strato you will need to add the [[StratoClientModule]] yourself.
- */
-object ProductMixerModule extends TwitterModule {
-
- override val modules = Seq(
- ABDeciderModule,
- ConfigApiModule,
- DeciderModule,
- FeatureSwitchesModule,
- LanguagesModule,
- PipelineExecutionLoggerModule,
- ProductMixerFlagModule,
- new ProductScopeModule(),
- ScalaObjectMapperModule,
- ThriftClientIdModule,
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala
deleted file mode 100644
index fc5680aa1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.core.module
-
-import com.google.inject.Provides
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.ssl.OpportunisticTls
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.StratoLocalRequestTimeout
-import com.twitter.strato.client.Client
-import com.twitter.strato.client.Strato
-import com.twitter.util.Duration
-import javax.inject.Singleton
-
-/**
- * Product Mixer prefers to use a single strato client module over having a variety with different
- * timeouts. Latency Budgets in Product Mixer systems should be defined at the application layer.
- */
-object StratoClientModule extends TwitterModule {
-
- @Provides
- @Singleton
- def providesStratoClient(
- serviceIdentifier: ServiceIdentifier,
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- @Flag(StratoLocalRequestTimeout) timeout: Option[Duration]
- ): Client = {
- val stratoClient = Strato.client.withMutualTls(serviceIdentifier, OpportunisticTls.Required)
-
- // For local development it can be useful to have a larger timeout than the Strato default of
- // 280ms. We strongly discourage setting client-level timeouts outside of this use-case. We
- // recommend setting an overall timeout for your pipeline's end-to-end running time.
- if (isServiceLocal && timeout.isDefined)
- stratoClient.withRequestTimeout(timeout.get).build()
- else {
- stratoClient.build()
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD
deleted file mode 100644
index 00b2668ca..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD
+++ /dev/null
@@ -1,15 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- ],
- exports = [
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala
deleted file mode 100644
index 6426928be..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.twitter.product_mixer.core.module.product_mixer_flags
-
-import com.twitter.inject.annotations.Flags
-import com.twitter.inject.Injector
-import com.twitter.inject.TwitterModule
-import com.twitter.util.Duration
-
-object ProductMixerFlagModule extends TwitterModule {
- final val ServiceLocal = "service.local"
- final val ConfigRepoLocalPath = "configrepo.local_path"
- final val FeatureSwitchesPath = "feature_switches.path"
- final val StratoLocalRequestTimeout = "strato.local.request_timeout"
- final val ScribeABImpressions = "scribe.ab_impressions"
- final val PipelineExecutionLoggerAllowList = "pipeline_execution_logger.allow_list"
-
- flag[Boolean](
- name = ServiceLocal,
- default = false,
- help = "Is the server running locally or in a DC")
-
- flag[String](
- name = ConfigRepoLocalPath,
- default = System.getProperty("user.home") + "/workspace/config",
- help = "Path to your local config repo"
- )
-
- flag[Boolean](
- name = ScribeABImpressions,
- help = "Enable scribing of AB impressions"
- )
-
- flag[String](
- name = FeatureSwitchesPath,
- help = "Path to your local config repo"
- )
-
- flag[Duration](
- name = StratoLocalRequestTimeout,
- help = "Override the request timeout for Strato when running locally"
- )
-
- flag[Seq[String]](
- name = PipelineExecutionLoggerAllowList,
- default = Seq.empty,
- help =
- "Specify user role(s) for which detailed log messages (containing PII) can be made. Accepts a single role or a comma separated list 'a,b,c'"
- )
-
- /**
- * Invoked at the end of server startup.
- *
- * If we're running locally, we display a nice message and a link to the admin page
- */
- override def singletonPostWarmupComplete(injector: Injector): Unit = {
- val isLocalService = injector.instance[Boolean](Flags.named(ServiceLocal))
- if (isLocalService) {
- // Extract service name from clientId since there isn't a specific flag for that
- val clientId = injector.instance[String](Flags.named("thrift.clientId"))
- val name = clientId.split("\\.")(0)
-
- val adminPort = injector.instance[String](Flags.named("admin.port"))
- val url = s"http://localhost$adminPort/"
-
- // Print instead of log, so it goes on stdout and doesn't get the logging decorations.
- // Update our local development recipe (local-development.rst) if making changes to this
- // message.
- println("===============================================================================")
- println(s"Welcome to a Product Mixer Service, $name")
- println(s"You can view the admin endpoint and thrift web forms at $url")
- println("Looking for support? Have questions? #product-mixer on Slack.")
- println("===============================================================================")
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD
deleted file mode 100644
index ad9cb35b3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/sources",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/sources/refreshing",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
- exports = [
- "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala
deleted file mode 100644
index 3db236d9d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.twitter.product_mixer.core.module.stringcenter
-
-import com.google.inject.Provides
-import com.twitter.abdecider.LoggingABDecider
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.util.jackson.ScalaObjectMapper
-import com.twitter.inject.TwitterModule
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.product.guice.scope.ProductScoped
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.stringcenter.client.ExternalStringRegistry
-import com.twitter.stringcenter.client.StringCenter
-import com.twitter.stringcenter.client.StringCenterClientConfig
-import com.twitter.stringcenter.client.sources.RefreshingStringSource
-import com.twitter.stringcenter.client.sources.RefreshingStringSourceConfig
-import com.twitter.stringcenter.client.sources.StringSource
-import com.twitter.translation.Languages
-import javax.inject.Singleton
-import scala.collection.concurrent
-
-/*
- * Fun trivia - this has to be a Class not an Object, otherwise when you ./bazel test blah/...
- * and glob multiple feature tests together it'll reuse the concurrentMaps below across
- * executions / different server objects.
- */
-class ProductScopeStringCenterModule extends TwitterModule {
-
- private val loadNothing =
- flag[Boolean](name = "stringcenter.dontload", default = false, help = "Avoid loading any files")
-
- flag[Boolean](
- name = "stringcenter.handle.language.fallback",
- default = true,
- help = "Handle language fallback for services that don't already handle it")
-
- flag[String](
- name = "stringcenter.default_bundle_path",
- default = "stringcenter",
- help = "The path on disk to the default bundle available at startup time")
-
- private val refreshingInterval = flag[Int](
- name = "stringcenter.refresh_interval_minutes",
- default = 3,
- help = "How often to poll the refreshing bundle path to check for new bundles")
-
- /* The Guice injector is single threaded, but out of a preponderance of caution we use a concurrent Map.
- *
- * We need to ensure that we only build one StringSource, StringCenter client, and External String
- * Registry for each String Center Project. @ProductScoped doesn't ensure this on it's own as
- * two products can have the same String Center Project set.
- */
- val stringSources: concurrent.Map[String, StringSource] = concurrent.TrieMap.empty
- val stringCenterClients: concurrent.Map[String, StringCenter] = concurrent.TrieMap.empty
- val externalStringRegistries: concurrent.Map[String, ExternalStringRegistry] =
- concurrent.TrieMap.empty
-
- @ProductScoped
- @Provides
- def providesStringCenterClients(
- abDecider: LoggingABDecider,
- stringSource: StringSource,
- languages: Languages,
- statsReceiver: StatsReceiver,
- clientConfig: StringCenterClientConfig,
- product: Product
- ): StringCenter = {
- stringCenterClients.getOrElseUpdate(
- stringCenterForProduct(product), {
- new StringCenter(
- abDecider,
- stringSource,
- languages,
- statsReceiver,
- clientConfig
- )
- })
- }
-
- @ProductScoped
- @Provides
- def providesExternalStringRegistries(
- product: Product
- ): ExternalStringRegistry = {
- externalStringRegistries.getOrElseUpdate(
- stringCenterForProduct(product), {
- new ExternalStringRegistry()
- })
- }
-
- @ProductScoped
- @Provides
- def providesStringCenterSources(
- mapper: ScalaObjectMapper,
- statsReceiver: StatsReceiver,
- product: Product,
- @Flag("stringcenter.default_bundle_path") defaultBundlePath: String
- ): StringSource = {
- if (loadNothing()) {
- StringSource.Empty
- } else {
- val stringCenterProduct = stringCenterForProduct(product)
-
- stringSources.getOrElseUpdate(
- stringCenterProduct, {
- val config = RefreshingStringSourceConfig(
- stringCenterProduct,
- defaultBundlePath,
- "stringcenter/downloaded/current/stringcenter",
- refreshingInterval().minutes
- )
- new RefreshingStringSource(
- config,
- mapper,
- statsReceiver
- .scope("StringCenter", "refreshing", "project", stringCenterProduct))
- }
- )
- }
- }
-
- private def stringCenterForProduct(product: Product): String =
- product.stringCenterProject.getOrElse {
- throw new UnsupportedOperationException(
- s"No StringCenter project defined for Product ${product.identifier}")
- }
-
- @Singleton
- @Provides
- def providesStringCenterClientConfig(
- @Flag("stringcenter.handle.language.fallback") handleLanguageFallback: Boolean
- ): StringCenterClientConfig = {
- StringCenterClientConfig(handleLanguageFallback = handleLanguageFallback)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD
deleted file mode 100644
index bbb46c4c3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD
+++ /dev/null
@@ -1,92 +0,0 @@
-scala_library(
- name = "query",
- sources = ["PipelineQuery.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- ],
-)
-
-scala_library(
- name = "executor",
- sources = [
- "FailOpenPolicy.scala",
- "PipelineResult.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "util/util-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "util/util-core",
- ],
-)
-
-scala_library(
- sources = [
- "!FailOpenPolicy.scala",
- "!PipelineQuery.scala",
- "!PipelineResult.scala",
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- ":executor",
- ":query",
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "scrooge/scrooge-serializer/src/main/scala",
- "stitch/stitch-core",
- ],
- exports = [
- ":executor",
- ":query",
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "scrooge/scrooge-serializer/src/main/scala",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala
deleted file mode 100644
index 49a31cbec..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-private[core] object CandidatePipelineResults
- extends Feature[PipelineQuery, Seq[CandidateWithDetails]]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala
deleted file mode 100644
index f36664e1d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory
-
-/**
- * [[FailOpenPolicy]] determines what should happen in the event that a candidate pipeline fails
- * to execute successfully.
- *
- * Exercise caution when creating new fail open policies. Product Mixer will fail open by default in
- * certain error cases (e.g. closed gate on a candidate pipeline) but these might inadvertently be
- * excluded by a new policy.
- */
-trait FailOpenPolicy {
- def apply(failureCategory: PipelineFailureCategory): Boolean
-}
-
-object FailOpenPolicy {
-
- /**
- * Always fail open on candidate pipeline failures except
- * for [[MisconfiguredFeatureMapFailure]]s because it's a programmer error
- * and should always fail loudly, even with an [[Always]] p[[FailOpenPolicy]]
- */
- val Always: FailOpenPolicy = (category: PipelineFailureCategory) => {
- category != MisconfiguredFeatureMapFailure
- }
-
- /**
- * Never fail open on candidate pipeline failures.
- *
- * @note this is more restrictive than the default behavior which is to allow gate closed
- * failures.
- */
- val Never: FailOpenPolicy = (_: PipelineFailureCategory) => false
-
- // Build a policy that will fail open for a given set of categories
- def apply(categories: Set[PipelineFailureCategory]): FailOpenPolicy =
- (failureCategory: PipelineFailureCategory) =>
- categories
- .contains(failureCategory)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala
deleted file mode 100644
index 889f1f8e4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-
-case class InvalidStepStateException(step: PipelineStepIdentifier, missingData: String)
- extends Exception(
- s"Invalid Step State: Step $step requires $missingData"
- )
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala
deleted file mode 100644
index 14e8b0778..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.state.HasResult
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor.Context
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Arrow.Iso
-import com.twitter.util.Return
-import com.twitter.util.Throw
-
-/**
- * Pipeline Arrow Builder used for constructing a final arrow for a pipeline after adding necessary
- * steps.
- *
- * @param steps The kept non-empty Pipeline Steps
- * @param addedSteps Steps that have been added, but not necessarily kept.
- * @param statsReceiver Stats Receiver for metric book keeping
- * @tparam Result sThe expected final result type of the pipeline.
- * @tparam State The input state type, which should implement [[HasResult]].
- */
-case class NewPipelineArrowBuilder[
- Result,
- State <: HasExecutorResults[State] with HasResult[Result]
-] private (
- private val steps: Seq[PipelineStep[State, _, _, _]],
- override val statsReceiver: StatsReceiver)
- extends Executor {
-
- def add[Config, ExecutorInput, ExResult <: ExecutorResult](
- pipelineStepIdentifier: PipelineStepIdentifier,
- step: Step[State, Config, ExecutorInput, ExResult],
- executorConfig: Config
- ): NewPipelineArrowBuilder[Result, State] = {
- require(
- !steps.contains(pipelineStepIdentifier),
- s"Found duplicate step $pipelineStepIdentifier when building pipeline arrow")
-
- // If the step has nothing to execute, drop it for simplification but still added it to the
- // "addedSteps" field for build time validation
- if (step.isEmpty(executorConfig)) {
- this
- } else {
- val newPipelineStep =
- PipelineStep(pipelineStepIdentifier, executorConfig, step)
- val newSteps = steps :+ newPipelineStep
- this.copy(steps = newSteps)
- }
- }
-
- def buildArrow(
- context: Executor.Context
- ): Arrow[State, NewPipelineResult[Result]] = {
- val initialArrow = Arrow
- .map { input: State => NewStepData[State](input) }
- val allStepArrows = steps.map { step =>
- Iso.onlyIf[NewStepData[State]] { stepData => !stepData.stopExecuting } {
- wrapStepWithExecutorBookkeeping(step, context)
- }
- }
- val combinedArrow = isoArrowsSequentially(allStepArrows)
- val resultArrow = Arrow.map { stepData: NewStepData[State] =>
- stepData.pipelineFailure match {
- case Some(failure) =>
- NewPipelineResult.Failure(failure, stepData.pipelineState.executorResultsByPipelineStep)
- case None =>
- NewPipelineResult.Success(
- stepData.pipelineState.buildResult,
- stepData.pipelineState.executorResultsByPipelineStep)
- }
- }
- initialArrow.andThen(combinedArrow).andThen(resultArrow)
- }
-
- private[this] def wrapStepWithExecutorBookkeeping(
- step: PipelineStep[State, _, _, _],
- context: Context
- ): Arrow.Iso[NewStepData[State]] = {
- val wrapped = wrapStepWithExecutorBookkeeping[NewStepData[State], NewStepData[State]](
- context = context,
- identifier = step.stepIdentifier,
- arrow = step.arrow(context),
- // extract the failure only if it's present. Not sure if this is needed???
- transformer = _.pipelineFailure.map(Throw(_)).getOrElse(Return.Unit)
- )
-
- Arrow
- .zipWithArg(wrapped.liftToTry)
- .map {
- case (_: NewStepData[State], Return(result)) =>
- // if Step was successful, return the result
- result
- case (previous: NewStepData[State], Throw(pipelineFailure: PipelineFailure)) =>
- // if the Step failed in such a way that the failure was NOT captured
- // in the result object, then update the State with the failure
- previous.withFailure(pipelineFailure)
- case (_, Throw(ex)) =>
- // an exception was thrown which was not handled by the failure classifier
- // this only happens with cancellation exceptions which are re-thrown
- throw ex
- }
- }
-
- /**
- * Sets up stats [[com.twitter.finagle.stats.Gauge]]s for any [[QualityFactorStatus]]
- *
- * @note We use provideGauge so these gauges live forever even without a reference.
- */
- private[pipeline] def buildGaugesForQualityFactor(
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorStatus: QualityFactorStatus,
- statsReceiver: StatsReceiver
- ): Unit = {
- qualityFactorStatus.qualityFactorByPipeline.foreach {
- case (identifier, qualityFactor) =>
- // QF is a relative stat (since the parent pipeline is monitoring a child pipeline)
- val scopes = pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor"
- statsReceiver.provideGauge(scopes: _*) { qualityFactor.currentValue.toFloat }
- }
- }
-}
-
-object NewPipelineArrowBuilder {
- def apply[Result, InputState <: HasExecutorResults[InputState] with HasResult[Result]](
- statsReceiver: StatsReceiver
- ): NewPipelineArrowBuilder[Result, InputState] = {
- NewPipelineArrowBuilder(
- Seq.empty,
- statsReceiver
- )
- }
-}
-
-/**
- * This is a pipeline specific instance of a step, i.e, a generic step with the step identifier
- * within the pipeline and its executor configs.
- * @param stepIdentifier Step identifier of the step within a pipeline
- * @param executorConfig Config to execute the step with
- * @param step The underlying step to be used
- * @tparam InputState The input state object
- * @tparam ExecutorConfig The config expected for the given step
- * @tparam ExecutorInput Input for the underlying executor
- * @tparam ExecResult The result type
- */
-case class PipelineStep[
- State <: HasExecutorResults[State],
- PipelineStepConfig,
- ExecutorInput,
- ExecResult <: ExecutorResult
-](
- stepIdentifier: PipelineStepIdentifier,
- executorConfig: PipelineStepConfig,
- step: Step[State, PipelineStepConfig, ExecutorInput, ExecResult]) {
-
- def arrow(
- context: Executor.Context
- ): Arrow.Iso[NewStepData[State]] = {
- val inputArrow = Arrow.map { stepData: NewStepData[State] =>
- step.adaptInput(stepData.pipelineState, executorConfig)
- }
-
- Arrow
- .zipWithArg(inputArrow.andThen(step.arrow(executorConfig, context))).map {
- case (stepData: NewStepData[State], executorResult: ExecResult @unchecked) =>
- val updatedResultsByPipelineStep =
- stepData.pipelineState.executorResultsByPipelineStep + (stepIdentifier -> executorResult)
- val updatedPipelineState = step
- .updateState(stepData.pipelineState, executorResult, executorConfig).setExecutorResults(
- updatedResultsByPipelineStep)
-
- NewStepData(updatedPipelineState)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala
deleted file mode 100644
index a93d735d4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.state.HasResult
-
-/**
- * A pipeline builder that is responsible for taking a PipelineConfig and creating a final pipeline
- * from it. It provides an [[NewPipelineArrowBuilder]] for composing the pipeline's underlying arrow
- * from [[Step]]s.
- *
- * @tparam Config The Pipeline Config
- * @tparam PipelineArrowResult The expected final result
- * @tparam PipelineArrowState State object for maintaining state across the pipeline.
- * @tparam OutputPipeline The final pipeline
- */
-trait NewPipelineBuilder[
- Config <: PipelineConfig,
- PipelineArrowResult,
- PipelineArrowState <: HasExecutorResults[PipelineArrowState] with HasResult[PipelineArrowResult],
- OutputPipeline <: Pipeline[_, _]] {
-
- type ArrowResult = PipelineArrowResult
- type ArrowState = PipelineArrowState
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- arrowBuilder: NewPipelineArrowBuilder[ArrowResult, ArrowState],
- config: Config
- ): OutputPipeline
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala
deleted file mode 100644
index 0e473dfc3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.ExecutorResult
-import scala.collection.immutable.ListMap
-
-sealed trait NewPipelineResult[-Result] {
- def executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult]
-}
-
-object NewPipelineResult {
- case class Failure(
- failure: PipelineFailure,
- override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult])
- extends NewPipelineResult[Any]
-
- case class Success[Result](
- result: Result,
- override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult])
- extends NewPipelineResult[Result]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala
deleted file mode 100644
index 3981d316c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-
-case class NewStepData[State <: HasExecutorResults[State]](
- pipelineState: State,
- pipelineFailure: Option[PipelineFailure] = None) {
-
- val stopExecuting = pipelineFailure.isDefined
- def withFailure(failure: PipelineFailure): NewStepData[State] =
- this.copy(pipelineFailure = Some(failure))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala
deleted file mode 100644
index c53ec81ed..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-
-/** Base trait for all `pipeline` implementations */
-trait Pipeline[-Query, Result] extends Component {
-
- /** The [[PipelineConfig]] that was used to create this [[Pipeline]] */
- private[core] val config: PipelineConfig
-
- /** Returns the underlying arrow that represents the pipeline. This is a val because we want to ensure
- * that the arrow is long-lived and consistent, not generated per-request.
- *
- * Directly using this arrow allows you to combine it with other arrows efficiently.
- */
- val arrow: Arrow[Query, PipelineResult[Result]]
-
- /** all child [[Component]]s that this [[Pipeline]] contains which will be registered and monitored */
- val children: Seq[Component]
-
- /**
- * A helper for executing a single query.
- *
- * toResultTry and lowerFromTry has the end result of adapting PipelineResult into either a
- * successful result or a Stitch exception, which is a common use-case for callers,
- * particularly in the case of [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]].
- */
- def process(query: Query): Stitch[Result] = arrow(query).map(_.toResultTry).lowerFromTry
-
- final override def toString = s"Pipeline(identifier=$identifier)"
-
- /**
- * [[Pipeline]]s are equal to one another if they were generated from the same [[PipelineConfig]],
- * we check this by doing a reference checks first then comparing the [[PipelineConfig]] instances.
- *
- * We can skip additional checks because the other fields (e.g. [[identifier]] and [[children]])
- * are derived from the [[PipelineConfig]].
- */
- final override def equals(obj: Any): Boolean = obj match {
- case pipeline: Pipeline[_, _] =>
- pipeline.eq(this) || pipeline.config.eq(config) || pipeline.config == config
- case _ => false
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala
deleted file mode 100644
index 377c06233..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala
+++ /dev/null
@@ -1,194 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor.Context
-import com.twitter.product_mixer.core.service
-import com.twitter.stitch.Arrow
-import com.twitter.util.Return
-import com.twitter.util.Throw
-
-trait PipelineBuilder[Query] extends Executor {
-
- /**
- * When a step is mostly the same, but only the result update changes,
- * you can pass in a [[ResultUpdater]] to the [[Step]] to perform the update
- * such as with multi-step hydration.
- */
- trait ResultUpdater[R <: PipelineResult[_], ER <: service.ExecutorResult] {
- def apply(existingResult: R, executorResult: ER): R
- }
-
- type UnderlyingResultType
- type PipelineResultType <: PipelineResult[UnderlyingResultType]
-
- /** the data that every step has as input and output - the query, and the in-progress result */
- case class StepData(query: Query, result: PipelineResultType)
-
- /** An [[Arrow.Iso]] [[Arrow]] is an arrow with the same input and output types. */
- type StepArrow = Arrow.Iso[StepData]
-
- /**
- * We break pipeline execution into a linear sequence of [[Step]]s. The execution logic of each
- * step is represented as an [[Executor]] (which is reusable between pipelines).
- *
- * Each step has access to the [[PipelineResult]] generated by previous steps, and can update it
- * with some new data.
- *
- * We define a pipeline Step as having three parts:
- *
- * - An underlying [[Executor]] [[Arrow]], from the underlying executor
- * - An input adaptor to extract the right data from the previous [[PipelineResult]]
- * - A result updater to update the [[PipelineResult]]
- *
- * This keeps knowledge of [[PipelineResult]] out of the executors, so they're reusable.
- *
- * @tparam ExecutorInput The input type used by the executor
- * @tparam ExecutorResult The output/result type used by the executor
- */
- trait Step[ExecutorInput, ExecutorResult] {
- def identifier: PipelineStepIdentifier
- def executorArrow: Arrow[ExecutorInput, ExecutorResult]
- def inputAdaptor(query: Query, previousResult: PipelineResultType): ExecutorInput
- def resultUpdater(
- previousPipelineResult: PipelineResultType,
- executorResult: ExecutorResult
- ): PipelineResultType
-
- /**
- * Optionally, steps can define a function to update the Query
- */
- def queryUpdater(query: Query, executorResult: ExecutorResult): Query = query
-
- /**
- * Arrow that adapts the input, runs the underlying Executor, adapts the output, and updates the state
- */
- val stepArrow: StepArrow = {
- val inputAdaptorArrow: Arrow[StepData, ExecutorInput] = Arrow.map { stepData: StepData =>
- inputAdaptor(stepData.query, stepData.result)
- }
- val outputAdaptorArrow: Arrow[(StepData, ExecutorResult), StepData] = Arrow.map {
- // abstract type pattern ExecutorResult is unchecked since it is eliminated by erasure
- case (previousStepData: StepData, executorResult: ExecutorResult @unchecked) =>
- StepData(
- query = queryUpdater(previousStepData.query, executorResult),
- result = resultUpdater(previousStepData.result, executorResult)
- )
- }
-
- Arrow
- .zipWithArg(inputAdaptorArrow.andThen(executorArrow))
- .andThen(outputAdaptorArrow)
- }
- }
-
- /**
- * Wraps a step with [[wrapStepWithExecutorBookkeeping]]
- *
- * When an error is encountered in execution, we update the [[PipelineResult.failure]] field,
- * and we return the partial results from all previously executed steps.
- */
- def wrapStepWithExecutorBookkeeping(
- context: Context,
- step: Step[_, _]
- ): Arrow.Iso[StepData] = {
- val wrapped = wrapStepWithExecutorBookkeeping[StepData, StepData](
- context = context,
- identifier = step.identifier,
- arrow = step.stepArrow,
- // extract the failure only if it's present
- transformer = _.result.failure match {
- case Some(pipelineFailure) => Throw(pipelineFailure)
- case None => Return.Unit
- }
- )
-
- Arrow
- .zipWithArg(wrapped.liftToTry)
- .map {
- case (_: StepData, Return(result)) =>
- // if Step was successful, return the result
- result
- case (StepData(query, previousResult), Throw(pipelineFailure: PipelineFailure)) =>
- // if the Step failed in such a way that the failure was NOT captured
- // in the result object, then update the State with the failure
- StepData(
- query,
- previousResult.withFailure(pipelineFailure).asInstanceOf[PipelineResultType])
- case (_, Throw(ex)) =>
- // an exception was thrown which was not handled by the failure classifier
- // this only happens with cancellation exceptions which are re-thrown
- throw ex
- }
- }
-
- /**
- * Builds a combined arrow out of steps.
- *
- * Wraps them in error handling, and only executes each step if the previous step is successful.
- */
- def buildCombinedArrowFromSteps(
- steps: Seq[Step[_, _]],
- context: Executor.Context,
- initialEmptyResult: PipelineResultType,
- stepsInOrderFromConfig: Seq[PipelineStepIdentifier]
- ): Arrow[Query, PipelineResultType] = {
-
- validateConfigAndBuilderAreInSync(steps, stepsInOrderFromConfig)
-
- /**
- * Prepare the step arrows.
- * 1. Wrap them in executor bookkeeping
- * 2. Wrap them in Iso.onlyIf - so we only execute them if we don't have a result or failure yet
- * 3. Combine them using [[isoArrowsSequentially]]
- *
- * @note this results in no Executor bookkeeping actions for [[Step]]s after
- * we reach a [[PipelineResult.stopExecuting]].
- */
- val stepArrows = isoArrowsSequentially(steps.map { step =>
- Arrow.Iso.onlyIf[StepData](stepData => !stepData.result.stopExecuting)(
- wrapStepWithExecutorBookkeeping(context, step))
- })
-
- Arrow
- .identity[Query]
- .map { query => StepData(query, initialEmptyResult) }
- .andThen(stepArrows)
- .map { case StepData(_, result) => result }
- }
-
- /**
- * Sets up stats [[com.twitter.finagle.stats.Gauge]]s for any [[QualityFactorStatus]]
- *
- * @note We use provideGauge so these gauges live forever even without a reference.
- */
- private[pipeline] def buildGaugesForQualityFactor(
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorStatus: QualityFactorStatus,
- statsReceiver: StatsReceiver
- ): Unit = {
- qualityFactorStatus.qualityFactorByPipeline.foreach {
- case (identifier, qualityFactor) =>
- // QF is a relative stat (since the parent pipeline is monitoring a child pipeline)
- val scopes = pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor"
- statsReceiver.provideGauge(scopes: _*) { qualityFactor.currentValue.toFloat }
- }
- }
-
- /** Validates that the [[PipelineConfigCompanion]] is in sync with the [[Step]]s a [[PipelineBuilder]] produces */
- private[this] def validateConfigAndBuilderAreInSync(
- builtSteps: Seq[Step[_, _]],
- stepsInOrder: Seq[PipelineStepIdentifier]
- ): Unit = {
- require(
- builtSteps.map(_.identifier) == stepsInOrder,
- s"Builder and Config are out of sync, bug in Product Mixer Core, `PipelineCompanion` and `PipelineBuilder` " +
- s"have different definitions of what Steps are run in this Pipeline \n" +
- s"${builtSteps.map(_.identifier).zip(stepsInOrder).mkString("\n")}"
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala
deleted file mode 100644
index 5b99e32fc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.model.common.identifier.HasComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-
-trait PipelineConfig extends HasComponentIdentifier
-
-trait PipelineConfigCompanion {
-
- /** used to generate `AsyncFeaturesFor` [[PipelineStepIdentifier]]s for the internal Async Features Step */
- private[core] def asyncFeaturesStep(
- stepToHydrateFor: PipelineStepIdentifier
- ): PipelineStepIdentifier =
- PipelineStepIdentifier("AsyncFeaturesFor" + stepToHydrateFor.name)
-
- /** All the Steps which are executed by a [[Pipeline]] in the order in which they are run */
- val stepsInOrder: Seq[PipelineStepIdentifier]
-
- val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set.empty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala
deleted file mode 100644
index 3428939e4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-/**
- * PipelineCursor represents any product-specific cursor model. Typically the PipelineCursor will be
- * a de-serialized base 64 thrift struct from initial request.
- */
-trait PipelineCursor
-
-/**
- * HasPipelineCursor indicates that a [[PipelineQuery]] has a cursor
- */
-trait HasPipelineCursor[+Cursor <: PipelineCursor] {
- def pipelineCursor: Option[Cursor]
-
- /**
- * If the cursor is not present, this typically means that we are on the first page
- */
- def isFirstPage: Boolean = pipelineCursor.isEmpty
-}
-
-/**
- * UrtPipelineCursor represents a URT product-specific cursor model. Typically the UrtPipelineCursor
- * will be a de-serialized base 64 thrift struct from initial request.
- */
-trait UrtPipelineCursor extends PipelineCursor {
-
- /** See [[UrtCursorBuilder]] for background on building initialSortIndex */
- def initialSortIndex: Long
-}
-
-object UrtPipelineCursor {
- def getCursorInitialSortIndex(query: PipelineQuery with HasPipelineCursor[_]): Option[Long] = {
- query.pipelineCursor match {
- case Some(cursor: UrtPipelineCursor) => Some(cursor.initialSortIndex)
- case _ => None
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala
deleted file mode 100644
index 6ed6a9ce2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.scrooge.BinaryThriftStructSerializer
-import com.twitter.scrooge.ThriftStruct
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-
-/**
- * Serializes a [[PipelineCursor]] into thrift and then into a base64 encoded string
- */
-trait PipelineCursorSerializer[-Cursor <: PipelineCursor] {
- def serializeCursor(cursor: Cursor): String
-}
-
-object PipelineCursorSerializer {
-
- /**
- * Deserializes a cursor string into thrift and then into a [[PipelineCursor]]
- *
- * @param cursorString to deserialize, which is base64 encoded thrift
- * @param cursorThriftSerializer to deserialize the cursor string into thrift
- * @param deserializePf specifies how to transform the serialized thrift into a [[PipelineCursor]]
- * @return optional [[PipelineCursor]]. `None` may or may not be a failure depending on the
- * implementation of deserializePf.
- *
- * @note The "A" type of deserializePf cannot be inferred due to the thrift type not being present
- * on the PipelineCursorSerializer trait. Therefore invokers must often add an explicit type
- * on the deserializeCursor call to help out the compiler when passing deserializePf inline.
- * Alternatively, deserializePf can be declared as a val with a type annotation before it is
- * passed into this method.
- */
- def deserializeCursor[Thrift <: ThriftStruct, Cursor <: PipelineCursor](
- cursorString: String,
- cursorThriftSerializer: BinaryThriftStructSerializer[Thrift],
- deserializePf: PartialFunction[Option[Thrift], Option[Cursor]]
- ): Option[Cursor] = {
- val thriftCursor: Option[Thrift] =
- Try {
- cursorThriftSerializer.fromString(cursorString)
- } match {
- case Return(thriftCursor) => Some(thriftCursor)
- case Throw(_) => None
- }
-
- // Add type annotation to help out the compiler since the type is lost due to the _ match
- val defaultDeserializePf: PartialFunction[Option[Thrift], Option[Cursor]] = {
- case _ =>
- // This case is the result of the client submitting a cursor we do not expect
- throw PipelineFailure(MalformedCursor, s"Unknown request cursor: $cursorString")
- }
-
- (deserializePf orElse defaultDeserializePf)(thriftCursor)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala
deleted file mode 100644
index ae6add7e1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.marshalling.request.HasClientContext
-import com.twitter.product_mixer.core.model.marshalling.request.HasDebugOptions
-import com.twitter.product_mixer.core.model.marshalling.request.HasProduct
-import com.twitter.timelines.configapi.HasParams
-import com.twitter.timelines.configapi.Param
-import com.twitter.util.Time
-
-trait PipelineQuery extends HasParams with HasClientContext with HasProduct with HasDebugOptions {
- self =>
-
- /** Set a query time val that is constant for the duration of the query lifecycle */
- val queryTime: Time = self.debugOptions.flatMap(_.requestTimeOverride).getOrElse(Time.now)
-
- /** The requested max results is specified, or not specified, by the thrift client */
- def requestedMaxResults: Option[Int]
-
- /** Retrieves the max results with a default Param, if not specified by the thrift client */
- def maxResults(defaultRequestedMaxResultParam: Param[Int]): Int =
- requestedMaxResults.getOrElse(params(defaultRequestedMaxResultParam))
-
- /** Optional [[FeatureMap]], this may be updated later using [[withFeatureMap]] */
- def features: Option[FeatureMap]
-
- /**
- * Since Query-Level features can be hydrated later, we need this method to update the PipelineQuery
- * usually this will be implemented via `copy(features = Some(features))`
- */
- def withFeatureMap(features: FeatureMap): PipelineQuery
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala
deleted file mode 100644
index f7e378917..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.core.pipeline
-
-import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ExecutionFailed
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-
-/**
- * Pipelines return a PipelineResult.
- *
- * This allows us to return a single main result (optionally, incase the pipeline didn't execute successfully), but
- * still have a detailed response object to show how that result was produced.
- */
-trait PipelineResult[ResultType] {
- val failure: Option[PipelineFailure]
- val result: Option[ResultType]
-
- def withFailure(failure: PipelineFailure): PipelineResult[ResultType]
- def withResult(result: ResultType): PipelineResult[ResultType]
-
- def resultSize(): Int
-
- private[pipeline] def stopExecuting: Boolean = failure.isDefined || result.isDefined
-
- final def toTry: Try[this.type] = (result, failure) match {
- case (_, Some(failure)) =>
- Throw(failure)
- case (_: Some[ResultType], _) =>
- Return(this)
- // Pipelines should always finish with either a result or a failure
- case _ => Throw(PipelineFailure(ExecutionFailed, "Pipeline did not execute"))
- }
-
- final def toResultTry: Try[ResultType] = {
- // `.get` is safe here because `toTry` guarantees a value in the `Return` case
- toTry.map(_.result.get)
- }
-}
-
-object PipelineResult {
-
- /**
- * Track number of candidates returned by a Pipeline. Cursors are excluded from this
- * count and modules are counted as the sum of their candidates.
- *
- * @note this is a somewhat subjective measure of 'size' and it is spread across pipeline
- * definitions as well as selectors.
- */
- def resultSize(results: Seq[CandidateWithDetails]): Int = results.map {
- case module: ModuleCandidateWithDetails => resultSize(module.candidates)
- case ItemCandidateWithDetails(_: CursorCandidate, _, _) => 0
- case _ => 1
- }.sum
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD
deleted file mode 100644
index 642e7c74f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD
+++ /dev/null
@@ -1,77 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-decider",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "configapi/configapi-decider",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala
deleted file mode 100644
index 2c52636b6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Arrow
-
-/**
- * A Candidate Pipeline
- *
- * This is an abstract class, as we only construct these via the [[CandidatePipelineBuilder]].
- *
- * A [[CandidatePipeline]] is capable of processing requests (queries) and returning candidates
- * in the form of a [[CandidatePipelineResult]]
- *
- * @tparam Query the domain model for the query or request
- */
-abstract class CandidatePipeline[-Query <: PipelineQuery] private[candidate]
- extends Pipeline[CandidatePipeline.Inputs[Query], Seq[CandidateWithDetails]] {
- override private[core] val config: BaseCandidatePipelineConfig[Query, _, _, _]
- override val arrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult]
- override val identifier: CandidatePipelineIdentifier
-}
-
-object CandidatePipeline {
- case class Inputs[+Query <: PipelineQuery](
- query: Query,
- existingCandidates: Seq[CandidateWithDetails])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala
deleted file mode 100644
index 2d3df3440..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala
+++ /dev/null
@@ -1,735 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.gate.ParamGate
-import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix
-import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.InvalidStepStateException
-import com.twitter.product_mixer.core.pipeline.PipelineBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult
-import com.twitter.product_mixer.core.service.candidate_source_executor.FetchedCandidateWithFeatures
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorInput
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.stitch.Arrow
-import com.twitter.util.logging.Logging
-import javax.inject.Inject
-
-class CandidatePipelineBuilder[
- Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result <: UniversalNoun[Any]] @Inject() (
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- candidateDecoratorExecutor: CandidateDecoratorExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- candidateSourceExecutor: CandidateSourceExecutor,
- groupResultsExecutor: GroupResultsExecutor,
- filterExecutor: FilterExecutor,
- gateExecutor: GateExecutor,
- override val statsReceiver: StatsReceiver)
- extends PipelineBuilder[CandidatePipeline.Inputs[Query]]
- with Logging {
-
- override type UnderlyingResultType = Seq[CandidateWithDetails]
- override type PipelineResultType = IntermediateCandidatePipelineResult[Result]
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- config: BaseCandidatePipelineConfig[
- Query,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result
- ]
- ): CandidatePipeline[Query] = {
-
- val pipelineIdentifier = config.identifier
- val candidateSourceIdentifier = config.candidateSource.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- config.failureClassifier.orElse(StoppedGateException.classifier(ClosedGate))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val enabledGateOpt = config.enabledDeciderParam.map { deciderParam =>
- ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam)
- }
- val supportedClientGateOpt = config.supportedClientParam.map { param =>
- ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param)
- }
-
- /**
- * Evaluate enabled decider gate first since if it's off, there is no reason to proceed
- * Next evaluate supported client feature switch gate, followed by customer configured gates
- */
- val allGates = enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ config.gates
-
- // Dynamically replace the identifier of both transformers if config used the inline constructor
- // which sets a default identifier. We need to do this to ensure uniqueness of identifiers.
- val queryTransformer = BaseCandidatePipelineQueryTransformer.copyWithUpdatedIdentifier(
- config.queryTransformer,
- pipelineIdentifier)
-
- val resultsTransformer = CandidatePipelineResultsTransformer.copyWithUpdatedIdentifier(
- config.resultTransformer,
- pipelineIdentifier)
-
- val decorator = config.decorator.map(decorator =>
- CandidateDecorator.copyWithUpdatedIdentifier(decorator, pipelineIdentifier))
-
- val GatesStep = new Step[Query, GateExecutorResult] {
- override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.gatesStep
-
- override def executorArrow: Arrow[Query, GateExecutorResult] = {
- gateExecutor.arrow(allGates, context)
- }
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): Query =
- query.query
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: GateExecutorResult
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(underlyingResult =
- previousPipelineResult.underlyingResult.copy(gateResult = Some(executorResult)))
- }
-
- def queryFeatureHydrationStep(
- queryFeatureHydrators: Seq[BaseQueryFeatureHydrator[Query, _]],
- stepIdentifier: PipelineStepIdentifier,
- updater: ResultUpdater[CandidatePipelineResult, QueryFeatureHydratorExecutor.Result]
- ): Step[Query, QueryFeatureHydratorExecutor.Result] =
- new Step[Query, QueryFeatureHydratorExecutor.Result] {
- override def identifier: PipelineStepIdentifier = stepIdentifier
-
- override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] =
- queryFeatureHydratorExecutor.arrow(
- queryFeatureHydrators,
- CandidatePipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy,
- context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): Query = query.query
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: QueryFeatureHydratorExecutor.Result
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(
- underlyingResult = updater(previousPipelineResult.underlyingResult, executorResult))
-
- override def queryUpdater(
- query: CandidatePipeline.Inputs[Query],
- executorResult: QueryFeatureHydratorExecutor.Result
- ): CandidatePipeline.Inputs[Query] =
- CandidatePipeline.Inputs(
- query.query
- .withFeatureMap(
- query.query.features.getOrElse(
- FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query],
- query.existingCandidates)
- }
-
- def asyncFeaturesStep(
- stepToHydrateFor: PipelineStepIdentifier,
- context: Executor.Context
- ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] {
- override def identifier: PipelineStepIdentifier =
- CandidatePipelineConfig.asyncFeaturesStep(stepToHydrateFor)
-
- override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- asyncFeatureMapExecutor.arrow(stepToHydrateFor, identifier, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): AsyncFeatureMap =
- previousResult.underlyingResult.mergedAsyncQueryFeatures
- .getOrElse(
- throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures")
- )
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: AsyncFeatureMapExecutorResults
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(
- underlyingResult =
- previousPipelineResult.underlyingResult.copy(asyncFeatureHydrationResults =
- previousPipelineResult.underlyingResult.asyncFeatureHydrationResults match {
- case Some(existingResults) => Some(existingResults ++ executorResult)
- case None => Some(executorResult)
- }))
-
- override def queryUpdater(
- query: CandidatePipeline.Inputs[Query],
- executorResult: AsyncFeatureMapExecutorResults
- ): CandidatePipeline.Inputs[Query] =
- if (executorResult.featureMapsByStep
- .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) {
- query
- } else {
- val updatedQuery = query.query
- .withFeatureMap(
- query.query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep(
- stepToHydrateFor)).asInstanceOf[Query]
- CandidatePipeline.Inputs(updatedQuery, query.existingCandidates)
- }
- }
-
- val CandidateSourceStep =
- new Step[Query, CandidateSourceExecutorResult[Result]] {
- override def identifier: PipelineStepIdentifier =
- CandidatePipelineConfig.candidateSourceStep
-
- override def executorArrow: Arrow[
- Query,
- CandidateSourceExecutorResult[Result]
- ] =
- candidateSourceExecutor
- .arrow(
- config.candidateSource,
- queryTransformer,
- resultsTransformer,
- config.featuresFromCandidateSourceTransformers,
- context
- )
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): Query =
- query.query
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateSourceExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(underlyingResult =
- previousPipelineResult.underlyingResult.copy(
- candidateSourceResult =
- Some(executorResult.asInstanceOf[CandidateSourceExecutorResult[UniversalNoun[Any]]])
- ))
-
- override def queryUpdater(
- query: CandidatePipeline.Inputs[Query],
- executorResult: CandidateSourceExecutorResult[Result]
- ): CandidatePipeline.Inputs[Query] = {
- val updatedFeatureMap =
- query.query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.candidateSourceFeatureMap
- val updatedQuery = query.query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]
- CandidatePipeline.Inputs(updatedQuery, query.existingCandidates)
- }
- }
-
- val PreFilterFeatureHydrationPhase1Step =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] {
- override def identifier: PipelineStepIdentifier =
- CandidatePipelineConfig.preFilterFeatureHydrationPhase1Step
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.preFilterFeatureHydrationPhase1, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = {
- val candidateSourceExecutorResult =
- previousResult.underlyingResult.candidateSourceResult.getOrElse {
- throw InvalidStepStateException(identifier, "CandidateSourceResult")
- }
- CandidateFeatureHydratorExecutor.Inputs(
- query.query,
- candidateSourceExecutorResult.candidates
- .asInstanceOf[Seq[CandidateWithFeatures[Result]]])
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateFeatureHydratorExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] = {
- val candidateSourceExecutorResult =
- previousPipelineResult.underlyingResult.candidateSourceResult.getOrElse {
- throw InvalidStepStateException(identifier, "CandidateSourceResult")
- }
-
- val featureMapsFromPreFilter = executorResult.results.map { result =>
- result.candidate -> result.features
- }.toMap
-
- val mergedFeatureMaps = candidateSourceExecutorResult.candidates.map { candidate =>
- val candidateFeatureMap = candidate.features
- val preFilterFeatureMap =
- featureMapsFromPreFilter.getOrElse(
- candidate.candidate.asInstanceOf[Result],
- FeatureMap.empty)
-
- candidate.candidate.asInstanceOf[Result] -> (candidateFeatureMap ++ preFilterFeatureMap)
- }.toMap
-
- previousPipelineResult.copy(
- underlyingResult = previousPipelineResult.underlyingResult.copy(
- preFilterHydrationResult = Some(
- executorResult
- .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]])
- ),
- featureMaps = Some(mergedFeatureMaps)
- )
- }
- }
-
- val PreFilterFeatureHydrationPhase2Step =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] {
- override def identifier: PipelineStepIdentifier =
- CandidatePipelineConfig.preFilterFeatureHydrationPhase2Step
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.preFilterFeatureHydrationPhase2, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = {
- val candidates = previousResult.underlyingResult.preFilterHydrationResult.getOrElse {
- throw InvalidStepStateException(identifier, "PreFilterHydrationResult")
- }.results
- CandidateFeatureHydratorExecutor.Inputs(
- query.query,
- candidates.asInstanceOf[Seq[CandidateWithFeatures[Result]]]
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateFeatureHydratorExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] = {
-
- val featureMapsFromPreFilterPhase2 = executorResult.results.map { result =>
- result.candidate -> result.features
- }.toMap
-
- val mergedFeatureMaps = previousPipelineResult.featureMaps
- .getOrElse(throw InvalidStepStateException(identifier, "FeatureMaps"))
- .map {
- case (candidate, featureMap) =>
- val preFilterPhase2FeatureMap =
- featureMapsFromPreFilterPhase2.getOrElse(candidate, FeatureMap.empty)
-
- candidate -> (featureMap ++ preFilterPhase2FeatureMap)
- }
-
- previousPipelineResult.copy(
- underlyingResult = previousPipelineResult.underlyingResult.copy(
- preFilterHydrationResultPhase2 = Some(
- executorResult
- .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]])
- ),
- featureMaps = Some(mergedFeatureMaps)
- )
- }
- }
-
- val FiltersStep =
- new Step[(Query, Seq[CandidateWithFeatures[Result]]), FilterExecutorResult[Result]] {
- override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.filtersStep
-
- override def executorArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Result]]),
- FilterExecutorResult[
- Result
- ]
- ] =
- filterExecutor.arrow(config.filters, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): (Query, Seq[CandidateWithFeatures[Result]]) = {
- val candidates =
- previousResult.underlyingResult.candidateSourceResult
- .getOrElse {
- throw InvalidStepStateException(identifier, "CandidateSourceResult")
- }.candidates.map(_.candidate).asInstanceOf[Seq[Result]]
-
- val featureMaps = previousResult.featureMaps
- .getOrElse(throw InvalidStepStateException(identifier, "FeatureMaps"))
-
- (
- query.query,
- candidates.map(candidate =>
- CandidateWithFeaturesImpl(
- candidate,
- featureMaps.getOrElse(candidate, FeatureMap.empty))))
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: FilterExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(underlyingResult =
- previousPipelineResult.underlyingResult.copy(
- filterResult =
- Some(executorResult.asInstanceOf[FilterExecutorResult[UniversalNoun[Any]]])
- ))
- }
-
- val PostFilterFeatureHydrationStep =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] {
- override def identifier: PipelineStepIdentifier =
- CandidatePipelineConfig.postFilterFeatureHydrationStep
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.postFilterFeatureHydration, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = {
- val filterResult = previousResult.underlyingResult.filterResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "FilterResult")
- ).result.asInstanceOf[Seq[Result]]
-
- val featureMaps = previousResult.featureMaps.getOrElse(
- throw InvalidStepStateException(identifier, "FeatureMaps")
- )
-
- val filteredCandidates = filterResult.map { candidate =>
- CandidateWithFeaturesImpl(candidate, featureMaps.getOrElse(candidate, FeatureMap.empty))
- }
- CandidateFeatureHydratorExecutor.Inputs(query.query, filteredCandidates)
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateFeatureHydratorExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] = {
- val filterResult = previousPipelineResult.underlyingResult.filterResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "FilterResult")
- ).result.asInstanceOf[Seq[Result]]
-
- val featureMaps = previousPipelineResult.featureMaps.getOrElse(
- throw InvalidStepStateException(identifier, "FeatureMaps")
- )
-
- val postFilterFeatureMaps = executorResult.results.map { result =>
- result.candidate -> result.features
- }.toMap
-
- val mergedFeatureMaps = filterResult.map { candidate =>
- candidate ->
- (featureMaps
- .getOrElse(candidate, FeatureMap.empty) ++ postFilterFeatureMaps.getOrElse(
- candidate,
- FeatureMap.empty))
- }.toMap
-
- previousPipelineResult.copy(
- underlyingResult = previousPipelineResult.underlyingResult.copy(
- postFilterHydrationResult = Some(
- executorResult
- .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]])
- ),
- featureMaps = Some(mergedFeatureMaps)
- )
- }
- }
-
- val ScorersStep =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] {
- override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.scorersStep
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.scorers, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = {
- val filterResult = previousResult.underlyingResult.filterResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "FilterResult")
- ).result.asInstanceOf[Seq[Result]]
-
- val featureMaps = previousResult.featureMaps.getOrElse(
- throw InvalidStepStateException(identifier, "FeatureMaps")
- )
-
- val filteredCandidates = filterResult.map { candidate =>
- CandidateWithFeaturesImpl(candidate, featureMaps.getOrElse(candidate, FeatureMap.empty))
- }
- CandidateFeatureHydratorExecutor.Inputs(query.query, filteredCandidates)
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateFeatureHydratorExecutorResult[Result]
- ): IntermediateCandidatePipelineResult[Result] = {
- val filterResult = previousPipelineResult.underlyingResult.filterResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "FilterResult")
- ).result.asInstanceOf[Seq[Result]]
-
- val featureMaps = previousPipelineResult.featureMaps.getOrElse(
- throw InvalidStepStateException(identifier, "FeatureMaps")
- )
-
- val scoringFeatureMaps = executorResult.results.map { result =>
- result.candidate -> result.features
- }.toMap
-
- val mergedFeatureMaps = filterResult.map { candidate =>
- candidate ->
- (featureMaps
- .getOrElse(candidate, FeatureMap.empty) ++ scoringFeatureMaps.getOrElse(
- candidate,
- FeatureMap.empty))
- }.toMap
-
- previousPipelineResult.copy(
- underlyingResult = previousPipelineResult.underlyingResult.copy(
- scorersResult = Some(
- executorResult
- .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]])
- ),
- featureMaps = Some(mergedFeatureMaps)
- )
- }
- }
-
- val DecorationStep =
- new Step[(Query, Seq[CandidateWithFeatures[Result]]), CandidateDecoratorExecutorResult] {
- override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.decoratorStep
-
- override def executorArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Result]]),
- CandidateDecoratorExecutorResult
- ] =
- candidateDecoratorExecutor.arrow(decorator, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): (Query, Seq[CandidateWithFeatures[Result]]) = {
- val keptCandidates = previousResult.underlyingResult.filterResult
- .getOrElse {
- throw InvalidStepStateException(identifier, "FilterResult")
- }.result.asInstanceOf[Seq[Result]]
-
- val featureMaps = previousResult.featureMaps.getOrElse {
- throw InvalidStepStateException(identifier, "FeatureMaps")
- }
-
- (
- query.query,
- keptCandidates.map(candidate =>
- CandidateWithFeaturesImpl(
- candidate,
- featureMaps.getOrElse(candidate, FeatureMap.empty))))
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: CandidateDecoratorExecutorResult
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(underlyingResult =
- previousPipelineResult.underlyingResult.copy(
- candidateDecoratorResult = Some(executorResult)
- ))
- }
-
- /**
- * ResultStep is a synchronous step that basically takes the outputs from the other steps, groups modules,
- * and puts things into the final result object
- */
- val ResultStep = new Step[GroupResultsExecutorInput[Result], GroupResultsExecutorResult] {
- override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.resultStep
-
- override def executorArrow: Arrow[
- GroupResultsExecutorInput[Result],
- GroupResultsExecutorResult
- ] = groupResultsExecutor.arrow(pipelineIdentifier, candidateSourceIdentifier, context)
-
- override def inputAdaptor(
- query: CandidatePipeline.Inputs[Query],
- previousResult: IntermediateCandidatePipelineResult[Result]
- ): GroupResultsExecutorInput[Result] = {
-
- val underlying = previousResult.underlyingResult
-
- val keptCandidates = underlying.filterResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "FilterResult")
- ).result.asInstanceOf[Seq[Result]]
-
- val decorations = underlying.candidateDecoratorResult
- .getOrElse(
- throw InvalidStepStateException(identifier, "DecorationResult")
- ).result.map(decoration => decoration.candidate -> decoration.presentation).toMap
-
- val combinedFeatureMaps: Map[Result, FeatureMap] = previousResult.featureMaps.getOrElse(
- throw InvalidStepStateException(identifier, "FeatureMaps"))
-
- val filteredCandidates = keptCandidates.map { candidate =>
- val updatedMap = combinedFeatureMaps
- .get(candidate).getOrElse(FeatureMap.empty)
- FetchedCandidateWithFeatures(candidate, updatedMap)
- }
-
- GroupResultsExecutorInput(
- candidates = filteredCandidates,
- decorations = decorations
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: IntermediateCandidatePipelineResult[Result],
- executorResult: GroupResultsExecutorResult
- ): IntermediateCandidatePipelineResult[Result] =
- previousPipelineResult.copy(underlyingResult = previousPipelineResult.underlyingResult
- .copy(result = Some(executorResult.candidatesWithDetails)))
- }
-
- val builtSteps = Seq(
- GatesStep,
- queryFeatureHydrationStep(
- config.queryFeatureHydration,
- CandidatePipelineConfig.fetchQueryFeaturesStep,
- (pipelineResult, executorResult) =>
- pipelineResult.copy(queryFeatures = Some(executorResult))
- ),
- queryFeatureHydrationStep(
- config.queryFeatureHydrationPhase2,
- CandidatePipelineConfig.fetchQueryFeaturesPhase2Step,
- (pipelineResult, executorResult) =>
- pipelineResult.copy(
- queryFeaturesPhase2 = Some(executorResult),
- mergedAsyncQueryFeatures = Some(
- pipelineResult.queryFeatures
- .getOrElse(
- throw InvalidStepStateException(
- CandidatePipelineConfig.fetchQueryFeaturesPhase2Step,
- "QueryFeatures")
- ).asyncFeatureMap ++ executorResult.asyncFeatureMap)
- )
- ),
- asyncFeaturesStep(CandidatePipelineConfig.candidateSourceStep, context),
- CandidateSourceStep,
- asyncFeaturesStep(CandidatePipelineConfig.preFilterFeatureHydrationPhase1Step, context),
- PreFilterFeatureHydrationPhase1Step,
- asyncFeaturesStep(CandidatePipelineConfig.preFilterFeatureHydrationPhase2Step, context),
- PreFilterFeatureHydrationPhase2Step,
- asyncFeaturesStep(CandidatePipelineConfig.filtersStep, context),
- FiltersStep,
- asyncFeaturesStep(CandidatePipelineConfig.postFilterFeatureHydrationStep, context),
- PostFilterFeatureHydrationStep,
- asyncFeaturesStep(CandidatePipelineConfig.scorersStep, context),
- ScorersStep,
- asyncFeaturesStep(CandidatePipelineConfig.decoratorStep, context),
- DecorationStep,
- ResultStep
- )
-
- /** The main execution logic for this Candidate Pipeline. */
- val finalArrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult] =
- buildCombinedArrowFromSteps(
- steps = builtSteps,
- context = context,
- initialEmptyResult =
- IntermediateCandidatePipelineResult.empty[Result](config.candidateSource.identifier),
- stepsInOrderFromConfig = CandidatePipelineConfig.stepsInOrder
- ).map(_.underlyingResult)
-
- val configFromBuilder = config
- new CandidatePipeline[Query] {
- override private[core] val config: BaseCandidatePipelineConfig[Query, _, _, _] =
- configFromBuilder
- override val arrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult] =
- finalArrow
- override val identifier: CandidatePipelineIdentifier = pipelineIdentifier
- override val alerts: Seq[Alert] = config.alerts
- override val children: Seq[Component] =
- allGates ++
- config.queryFeatureHydration ++
- Seq(queryTransformer, config.candidateSource, resultsTransformer) ++
- config.featuresFromCandidateSourceTransformers ++
- decorator.toSeq ++
- config.preFilterFeatureHydrationPhase1 ++
- config.filters ++
- config.postFilterFeatureHydration ++
- config.scorers
- }
- }
-
- private case class CandidateWithFeaturesImpl(candidate: Result, features: FeatureMap)
- extends CandidateWithFeatures[Result]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala
deleted file mode 100644
index f488b341d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CandidatePipelineBuilderFactory @Inject() (
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- candidateDecoratorExecutor: CandidateDecoratorExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- candidateSourceExecutor: CandidateSourceExecutor,
- groupResultsExecutor: GroupResultsExecutor,
- filterExecutor: FilterExecutor,
- gateExecutor: GateExecutor,
- statsReceiver: StatsReceiver) {
- def get[
- Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result <: UniversalNoun[Any]
- ]: CandidatePipelineBuilder[
- Query,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result
- ] = {
- new CandidatePipelineBuilder[
- Query,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result
- ](
- queryFeatureHydratorExecutor,
- asyncFeatureMapExecutor,
- candidateDecoratorExecutor,
- candidateFeatureHydratorExecutor,
- candidateSourceExecutor,
- groupResultsExecutor,
- filterExecutor,
- gateExecutor,
- statsReceiver
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala
deleted file mode 100644
index bbdcb2d50..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala
+++ /dev/null
@@ -1,264 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.functional_component.transformer._
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineConfig
-import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-sealed trait BaseCandidatePipelineConfig[
- -Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result <: UniversalNoun[Any]]
- extends PipelineConfig {
-
- val identifier: CandidatePipelineIdentifier
-
- /**
- * A candidate pipeline can fetch query-level features for use within the candidate source. It's
- * generally recommended to set a hydrator in the parent recos or mixer pipeline if multiple
- * candidate pipelines share the same feature but if a specific query feature hydrator is used
- * by one pipeline and you don't want to block the others, you could explicitly set it here.
- * If a feature is hydrated both in the parent pipeline or here, this one takes priority.
- */
- def queryFeatureHydration: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty
-
- /**
- * For query-level features that are dependent on query-level features from [[queryFeatureHydration]]
- */
- def queryFeatureHydrationPhase2: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty
-
- /**
- * When these Params are defined, they will automatically be added as Gates in the pipeline
- * by the CandidatePipelineBuilder
- *
- * The enabled decider param can to be used to quickly disable a Candidate Pipeline via Decider
- */
- val enabledDeciderParam: Option[DeciderParam[Boolean]] = None
-
- /**
- * This supported client feature switch param can be used with a Feature Switch to control the
- * rollout of a new Candidate Pipeline from dogfood to experiment to production
- */
- val supportedClientParam: Option[FSParam[Boolean]] = None
-
- /** [[Gate]]s that are applied sequentially, the pipeline will only run if all the Gates are open */
- def gates: Seq[BaseGate[Query]] = Seq.empty
-
- /**
- * A pair of transforms to adapt the underlying candidate source to the pipeline's query and result types
- * Complex use cases such as those that need access to features should construct their own transformer, but
- * for simple use cases, you can pass in an anonymous function.
- * @example
- * {{{ override val queryTransformer: CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] = { query =>
- * query.toExampleThrift
- * }
- * }}}
- */
- def queryTransformer: BaseCandidatePipelineQueryTransformer[
- Query,
- CandidateSourceQuery
- ]
-
- /** Source for Candidates for this Pipeline */
- def candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult]
-
- /**
- * [[CandidateFeatureTransformer]] allow you to define [[com.twitter.product_mixer.core.feature.Feature]] extraction logic from your [[CandidateSource]] results.
- * If your candidate sources return [[com.twitter.product_mixer.core.feature.Feature]]s alongside the candidate that might be useful later on,
- * add transformers for constructing feature maps.
- *
- * @note If multiple transformers extract the same feature, the last one takes priority and is kept.
- */
- def featuresFromCandidateSourceTransformers: Seq[
- CandidateFeatureTransformer[CandidateSourceResult]
- ] = Seq.empty
-
- /**
- * a result Transformer may throw PipelineFailure for candidates that are malformed and
- * should be removed. This should be exceptional behavior, and not a replacement for adding a Filter.
- * Complex use cases such as those that need access to features should construct their own transformer, but
- * for simple use cases, you can pass in an anonymous function.
- * @example
- * {{{ override val queryTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Result] = { sourceResult =>
- * ExampleCandidate(sourceResult.id)
- * }
- * }}}
- *
- */
- val resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Result]
-
- /**
- * Before filters are run, you can fetch features for each candidate.
- *
- * Uses Stitch, so you're encouraged to use a working Stitch Adaptor to batch between candidates.
- *
- * The existing features (from the candidate source) are passed in as an input. You are not expected
- * to put them into the resulting feature map yourself - they will be merged for you by the platform.
- *
- * This API is likely to change when Product Mixer does managed feature hydration
- */
- val preFilterFeatureHydrationPhase1: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] =
- Seq.empty
-
- /**
- * A second phase of feature hydration that can be run before filtering and after the first phase
- * of [[preFilterFeatureHydrationPhase1]]. You are not expected to put them into the resulting
- * feature map yourself - they will be merged for you by the platform.
- */
- val preFilterFeatureHydrationPhase2: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] =
- Seq.empty
-
- /** A list of filters to apply. Filters will be applied in sequential order. */
- def filters: Seq[Filter[Query, Result]] = Seq.empty
-
- /**
- * After filters are run, you can fetch features for each candidate.
- *
- * Uses Stitch, so you're encouraged to use a working Stitch Adaptor to batch between candidates.
- *
- * The existing features (from the candidate source) & pre-filtering are passed in as an input.
- * You are not expected to put them into the resulting feature map yourself -
- * they will be merged for you by the platform.
- *
- * This API is likely to change when Product Mixer does managed feature hydration
- */
- val postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] = Seq.empty
-
- /**
- * Decorators allow for adding Presentations to candidates. While the Presentation can contain any
- * arbitrary data, Decorators are often used to add a UrtItemPresentation for URT item support, or
- * a UrtModulePresentation for grouping the candidates in a URT module.
- */
- val decorator: Option[CandidateDecorator[Query, Result]] = None
-
- /**
- * A candidate pipeline can define a partial function to rescue failures here. They will be treated as failures
- * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here).
- */
- def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty
-
- /**
- * Scorers for candidates. Scorers are executed in parallel. Order does not matter.
- */
- def scorers: Seq[Scorer[Query, Result]] = Seq.empty
-
- /**
- * Alerts can be used to indicate the pipeline's service level objectives. Alerts and
- * dashboards will be automatically created based on this information.
- */
- val alerts: Seq[Alert] = Seq.empty
-
- /**
- * This method is used by the product mixer framework to build the pipeline.
- */
- private[core] final def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- factory: CandidatePipelineBuilderFactory
- ): CandidatePipeline[Query] = {
- factory.get.build(parentComponentIdentifierStack, this)
- }
-}
-
-trait CandidatePipelineConfig[
- -Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result <: UniversalNoun[Any]]
- extends BaseCandidatePipelineConfig[
- Query,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result
- ] {
- override val gates: Seq[Gate[Query]] = Seq.empty
-
- override val queryTransformer: CandidatePipelineQueryTransformer[
- Query,
- CandidateSourceQuery
- ]
-}
-
-trait DependentCandidatePipelineConfig[
- -Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result <: UniversalNoun[Any]]
- extends BaseCandidatePipelineConfig[
- Query,
- CandidateSourceQuery,
- CandidateSourceResult,
- Result
- ]
-
-/**
- * Contains [[PipelineStepIdentifier]]s for the Steps that are available for all [[BaseCandidatePipelineConfig]]s
- */
-object CandidatePipelineConfig extends PipelineConfigCompanion {
- val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates")
- val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures")
- val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier = PipelineStepIdentifier(
- "FetchQueryFeaturesPhase2")
- val candidateSourceStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidateSource")
- val preFilterFeatureHydrationPhase1Step: PipelineStepIdentifier =
- PipelineStepIdentifier("PreFilterFeatureHydration")
- val preFilterFeatureHydrationPhase2Step: PipelineStepIdentifier =
- PipelineStepIdentifier("PreFilterFeatureHydrationPhase2")
- val filtersStep: PipelineStepIdentifier = PipelineStepIdentifier("Filters")
- val postFilterFeatureHydrationStep: PipelineStepIdentifier =
- PipelineStepIdentifier("PostFilterFeatureHydration")
- val scorersStep: PipelineStepIdentifier = PipelineStepIdentifier("Scorer")
- val decoratorStep: PipelineStepIdentifier = PipelineStepIdentifier("Decorator")
- val resultStep: PipelineStepIdentifier = PipelineStepIdentifier("Result")
-
- /** All the steps which are executed by a [[CandidatePipeline]] in the order in which they are run */
- override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq(
- gatesStep,
- fetchQueryFeaturesStep,
- fetchQueryFeaturesPhase2Step,
- asyncFeaturesStep(candidateSourceStep),
- candidateSourceStep,
- asyncFeaturesStep(preFilterFeatureHydrationPhase1Step),
- preFilterFeatureHydrationPhase1Step,
- asyncFeaturesStep(preFilterFeatureHydrationPhase2Step),
- preFilterFeatureHydrationPhase2Step,
- asyncFeaturesStep(filtersStep),
- filtersStep,
- asyncFeaturesStep(postFilterFeatureHydrationStep),
- postFilterFeatureHydrationStep,
- asyncFeaturesStep(scorersStep),
- scorersStep,
- asyncFeaturesStep(decoratorStep),
- decoratorStep,
- resultStep
- )
-
- override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set(
- candidateSourceStep,
- preFilterFeatureHydrationPhase1Step,
- preFilterFeatureHydrationPhase2Step,
- filtersStep,
- postFilterFeatureHydrationStep,
- scorersStep,
- decoratorStep
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala
deleted file mode 100644
index 7729cbcf8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-
-case class CandidatePipelineResult(
- candidateSourceIdentifier: CandidateSourceIdentifier,
- gateResult: Option[GateExecutorResult],
- queryFeatures: Option[QueryFeatureHydratorExecutor.Result],
- queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result],
- mergedAsyncQueryFeatures: Option[AsyncFeatureMap],
- candidateSourceResult: Option[CandidateSourceExecutorResult[UniversalNoun[Any]]],
- preFilterHydrationResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]],
- preFilterHydrationResultPhase2: Option[
- CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]
- ],
- filterResult: Option[FilterExecutorResult[UniversalNoun[Any]]],
- postFilterHydrationResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]],
- candidateDecoratorResult: Option[CandidateDecoratorExecutorResult],
- scorersResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]],
- asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults],
- failure: Option[PipelineFailure],
- result: Option[Seq[CandidateWithDetails]])
- extends PipelineResult[Seq[CandidateWithDetails]] {
-
- override def withFailure(failure: PipelineFailure): CandidatePipelineResult =
- copy(failure = Some(failure))
-
- override def withResult(
- result: Seq[CandidateWithDetails]
- ): CandidatePipelineResult = copy(result = Some(result))
-
- override val resultSize: Int = result.map(PipelineResult.resultSize).getOrElse(0)
-}
-
-private[candidate] object IntermediateCandidatePipelineResult {
- def empty[Candidate <: UniversalNoun[Any]](
- candidateSourceIdentifier: CandidateSourceIdentifier
- ): IntermediateCandidatePipelineResult[Candidate] = {
- IntermediateCandidatePipelineResult(
- CandidatePipelineResult(
- candidateSourceIdentifier = candidateSourceIdentifier,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None
- ),
- None
- )
- }
-}
-
-private[candidate] case class IntermediateCandidatePipelineResult[Candidate <: UniversalNoun[Any]](
- underlyingResult: CandidatePipelineResult,
- featureMaps: Option[Map[Candidate, FeatureMap]])
- extends PipelineResult[Seq[CandidateWithDetails]] {
- override val failure: Option[PipelineFailure] = underlyingResult.failure
- override val result: Option[Seq[CandidateWithDetails]] = underlyingResult.result
-
- override def withFailure(
- failure: PipelineFailure
- ): IntermediateCandidatePipelineResult[Candidate] =
- copy(underlyingResult = underlyingResult.withFailure(failure))
-
- override def withResult(
- result: Seq[CandidateWithDetails]
- ): IntermediateCandidatePipelineResult[Candidate] =
- copy(underlyingResult = underlyingResult.withResult(result))
-
- override def resultSize(): Int = underlyingResult.resultSize
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala
deleted file mode 100644
index 73baa8abb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.PassthroughCandidateSource
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateExtractor
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-object PassthroughCandidatePipelineConfig {
-
- /**
- * Build a [[PassthroughCandidatePipelineConfig]] with a [[PassthroughCandidateSource]] built from
- * a [[CandidateExtractor]]
- */
- def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- identifier: CandidatePipelineIdentifier,
- extractor: CandidateExtractor[Query, Candidate],
- decorator: Option[CandidateDecorator[Query, Candidate]] = None
- ): PassthroughCandidatePipelineConfig[Query, Candidate] = {
-
- // Renaming variables to keep the interface clean, but avoid naming collisions when creating
- // the anonymous class.
- val _identifier = identifier
- val _extractor = extractor
- val _decorator = decorator
-
- new PassthroughCandidatePipelineConfig[Query, Candidate] {
- override val identifier = _identifier
- override val candidateSource =
- PassthroughCandidateSource(CandidateSourceIdentifier(_identifier.name), _extractor)
- override val decorator = _decorator
- }
- }
-}
-
-trait PassthroughCandidatePipelineConfig[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends CandidatePipelineConfig[Query, Query, Candidate, Candidate] {
-
- override val queryTransformer: CandidatePipelineQueryTransformer[Query, Query] = identity
-
- override val resultTransformer: CandidatePipelineResultsTransformer[Candidate, Candidate] =
- identity
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala
deleted file mode 100644
index 2829e8334..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.candidate
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.candidate_source.StaticCandidateSource
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-
-object StaticCandidatePipelineConfig {
-
- /**
- * Build a [[StaticCandidatePipelineConfig]] with a [[CandidateSource]] that returns the [[candidate]]
- */
- def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- identifier: CandidatePipelineIdentifier,
- candidate: Candidate,
- decorator: Option[CandidateDecorator[Query, Candidate]] = None
- ): StaticCandidatePipelineConfig[Query, Candidate] = {
-
- // Renaming variables to keep the interface clean, but avoid naming collisions when creating
- // the anonymous class.
- val _identifier = identifier
- val _candidate = candidate
- val _decorator = decorator
-
- new StaticCandidatePipelineConfig[Query, Candidate] {
- override val identifier = _identifier
- override val candidate = _candidate
- override val decorator = _decorator
- }
- }
-}
-
-trait StaticCandidatePipelineConfig[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends CandidatePipelineConfig[Query, Unit, Unit, Candidate] {
-
- val candidate: Candidate
-
- override def candidateSource: CandidateSource[Unit, Unit] = StaticCandidateSource[Unit](
- identifier = CandidateSourceIdentifier(identifier.name),
- result = Seq(()))
-
- override val queryTransformer: CandidatePipelineQueryTransformer[Query, Unit] = _ => Unit
-
- override val resultTransformer: CandidatePipelineResultsTransformer[Unit, Candidate] = _ =>
- candidate
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD
deleted file mode 100644
index bbda52b47..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD
+++ /dev/null
@@ -1,62 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala
deleted file mode 100644
index 645e20bea..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.mixer
-
-import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Arrow
-
-/**
- * A Mixer Pipeline
- *
- * This is an abstract class, as we only construct these via the [[MixerPipelineBuilder]].
- *
- * A [[MixerPipeline]] is capable of processing requests (queries) and returning responses (results)
- * in the correct format to directly send to users.
- *
- * @tparam Query the domain model for the query or request
- * @tparam Result the final marshalled result type
- */
-abstract class MixerPipeline[Query <: PipelineQuery, Result] private[mixer]
- extends Pipeline[Query, Result] {
- override private[core] val config: MixerPipelineConfig[Query, _, Result]
- override val arrow: Arrow[Query, MixerPipelineResult[Result]]
- override val identifier: MixerPipelineIdentifier
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala
deleted file mode 100644
index 4cdb44552..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala
+++ /dev/null
@@ -1,582 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.mixer
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.InvalidStepStateException
-import com.twitter.product_mixer.core.pipeline.PipelineBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-import com.twitter.stitch.Arrow
-import com.twitter.util.logging.Logging
-
-/**
- * MixerPipelineBuilder builds [[MixerPipeline]]s from [[MixerPipelineConfig]]s.
- *
- * You should inject a [[MixerPipelineBuilderFactory]] and call `.get` to build these.
- *
- * @see [[MixerPipelineConfig]] for the description of the type parameters
- */
-class MixerPipelineBuilder[Query <: PipelineQuery, DomainResultType <: HasMarshalling, Result](
- candidatePipelineExecutor: CandidatePipelineExecutor,
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- domainMarshallerExecutor: DomainMarshallerExecutor,
- transportMarshallerExecutor: TransportMarshallerExecutor,
- pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory,
- override val statsReceiver: StatsReceiver)
- extends PipelineBuilder[Query]
- with Logging {
-
- override type UnderlyingResultType = Result
- override type PipelineResultType = MixerPipelineResult[Result]
-
- def qualityFactorStep(
- qualityFactorStatus: QualityFactorStatus
- ): Step[Query, QualityFactorExecutorResult] =
- new Step[Query, QualityFactorExecutorResult] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.qualityFactorStep
-
- override def executorArrow: Arrow[Query, QualityFactorExecutorResult] =
- Arrow
- .map[Query, QualityFactorExecutorResult] { _ =>
- QualityFactorExecutorResult(
- pipelineQualityFactors =
- qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue)
- )
- }
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): Query = query
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: QualityFactorExecutorResult
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(qualityFactorResult = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: QualityFactorExecutorResult
- ): Query = {
- query match {
- case queryWithQualityFactor: HasQualityFactorStatus =>
- queryWithQualityFactor
- .withQualityFactorStatus(
- queryWithQualityFactor.qualityFactorStatus.getOrElse(QualityFactorStatus.empty) ++
- qualityFactorStatus
- ).asInstanceOf[Query]
- case _ =>
- query
- }
- }
- }
-
- def gatesStep(
- gates: Seq[Gate[Query]],
- context: Executor.Context
- ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.gatesStep
-
- override def executorArrow: Arrow[Query, GateExecutorResult] =
- gateExecutor.arrow(gates, context)
-
- override def inputAdaptor(query: Query, previousResult: MixerPipelineResult[Result]): Query =
- query
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: GateExecutorResult
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(gateResult = Some(executorResult))
- }
-
- def fetchQueryFeaturesStep(
- queryFeatureHydrators: Seq[QueryFeatureHydrator[Query]],
- stepIdentifier: PipelineStepIdentifier,
- updater: ResultUpdater[MixerPipelineResult[Result], QueryFeatureHydratorExecutor.Result],
- context: Executor.Context
- ): Step[Query, QueryFeatureHydratorExecutor.Result] =
- new Step[Query, QueryFeatureHydratorExecutor.Result] {
- override def identifier: PipelineStepIdentifier = stepIdentifier
-
- override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] =
- queryFeatureHydratorExecutor.arrow(
- queryFeatureHydrators,
- MixerPipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy,
- context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): Query = query
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: QueryFeatureHydratorExecutor.Result
- ): MixerPipelineResult[Result] =
- updater(previousPipelineResult, executorResult)
-
- override def queryUpdater(
- query: Query,
- executorResult: QueryFeatureHydratorExecutor.Result
- ): Query =
- query
- .withFeatureMap(
- query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query]
- }
-
- def asyncFeaturesStep(
- stepToHydrateFor: PipelineStepIdentifier,
- context: Executor.Context
- ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] {
- override def identifier: PipelineStepIdentifier =
- MixerPipelineConfig.asyncFeaturesStep(stepToHydrateFor)
-
- override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- asyncFeatureMapExecutor.arrow(
- stepToHydrateFor,
- identifier,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): AsyncFeatureMap =
- previousResult.mergedAsyncQueryFeatures
- .getOrElse(
- throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures")
- )
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: AsyncFeatureMapExecutorResults
- ): MixerPipelineResult[Result] = previousPipelineResult.copy(
- asyncFeatureHydrationResults = previousPipelineResult.asyncFeatureHydrationResults match {
- case Some(existingResults) => Some(existingResults ++ executorResult)
- case None => Some(executorResult)
- })
-
- override def queryUpdater(
- query: Query,
- executorResult: AsyncFeatureMapExecutorResults
- ): Query =
- if (executorResult.featureMapsByStep
- .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) {
- query
- } else {
- query
- .withFeatureMap(
- query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep(
- stepToHydrateFor)).asInstanceOf[Query]
- }
- }
-
- def candidatePipelinesStep(
- candidatePipelines: Seq[CandidatePipeline[Query]],
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] =
- new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.candidatePipelinesStep
-
- override def executorArrow: Arrow[CandidatePipeline.Inputs[
- Query
- ], CandidatePipelineExecutorResult] =
- candidatePipelineExecutor
- .arrow(
- candidatePipelines,
- defaultFailOpenPolicy,
- failOpenPolicies,
- qualityFactorObserverByPipeline,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): CandidatePipeline.Inputs[Query] = CandidatePipeline.Inputs[Query](query, Seq.empty)
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: CandidatePipelineExecutorResult
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(candidatePipelineResults = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: CandidatePipelineExecutorResult
- ): Query = {
- val updatedFeatureMap = query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap
- query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]
- }
- }
-
- def dependentCandidatePipelinesStep(
- candidatePipelines: Seq[CandidatePipeline[Query]],
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] =
- new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- MixerPipelineConfig.dependentCandidatePipelinesStep
-
- override def executorArrow: Arrow[CandidatePipeline.Inputs[
- Query
- ], CandidatePipelineExecutorResult] =
- candidatePipelineExecutor
- .arrow(
- candidatePipelines,
- defaultFailOpenPolicy,
- failOpenPolicies,
- qualityFactorObserverByPipeline,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): CandidatePipeline.Inputs[Query] = {
- val previousCandidates = previousResult.candidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "Candidates")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
- CandidatePipeline.Inputs[Query](query, previousCandidates)
- }
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: CandidatePipelineExecutorResult
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(dependentCandidatePipelineResults = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: CandidatePipelineExecutorResult
- ): Query = {
- val updatedFeatureMap = query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap
- query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]
- }
- }
-
- def resultSelectorsStep(
- selectors: Seq[Selector[Query]],
- context: Executor.Context
- ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.resultSelectorsStep
-
- override def executorArrow: Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- selectorExecutor.arrow(selectors, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): SelectorExecutor.Inputs[Query] = {
- val candidates = previousResult.candidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "Candidates")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
-
- val dependentCandidates =
- previousResult.dependentCandidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "DependentCandidates")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
-
- SelectorExecutor.Inputs(
- query = query,
- candidatesWithDetails = candidates ++ dependentCandidates
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: SelectorExecutorResult
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(resultSelectorResults = Some(executorResult))
- }
-
- def domainMarshallingStep(
- domainMarshaller: DomainMarshaller[Query, DomainResultType],
- context: Executor.Context
- ): Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[
- DomainResultType
- ]] =
- new Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[
- DomainResultType
- ]] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.domainMarshallerStep
-
- override def executorArrow: Arrow[
- DomainMarshallerExecutor.Inputs[Query],
- DomainMarshallerExecutor.Result[DomainResultType]
- ] =
- domainMarshallerExecutor.arrow(domainMarshaller, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): DomainMarshallerExecutor.Inputs[Query] = {
- val selectorResults = previousResult.resultSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }
-
- DomainMarshallerExecutor.Inputs(
- query = query,
- candidatesWithDetails = selectorResults.selectedCandidates
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: DomainMarshallerExecutor.Result[DomainResultType]
- ): MixerPipelineResult[Result] = previousPipelineResult.copy(
- domainMarshallerResults = Some(executorResult)
- )
- }
-
- def resultSideEffectsStep(
- sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]],
- context: Executor.Context
- ): Step[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] = new Step[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.resultSideEffectsStep
-
- override def executorArrow: Arrow[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] = pipelineResultSideEffectExecutor.arrow(sideEffects, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = {
-
- val selectorResults = previousResult.resultSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }
-
- val domainMarshallerResults = previousResult.domainMarshallerResults.getOrElse {
- throw InvalidStepStateException(identifier, "DomainMarshallerResults")
- }
-
- PipelineResultSideEffect.Inputs[Query, DomainResultType](
- query = query,
- selectedCandidates = selectorResults.selectedCandidates,
- remainingCandidates = selectorResults.remainingCandidates,
- droppedCandidates = selectorResults.droppedCandidates,
- response = domainMarshallerResults.result.asInstanceOf[DomainResultType]
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: PipelineResultSideEffectExecutor.Result
- ): MixerPipelineResult[Result] =
- previousPipelineResult.copy(resultSideEffectResults = Some(executorResult))
- }
-
- def transportMarshallingStep(
- transportMarshaller: TransportMarshaller[DomainResultType, Result],
- context: Executor.Context
- ): Step[
- TransportMarshallerExecutor.Inputs[DomainResultType],
- TransportMarshallerExecutor.Result[Result]
- ] = new Step[TransportMarshallerExecutor.Inputs[
- DomainResultType
- ], TransportMarshallerExecutor.Result[Result]] {
- override def identifier: PipelineStepIdentifier = MixerPipelineConfig.transportMarshallerStep
-
- override def executorArrow: Arrow[TransportMarshallerExecutor.Inputs[
- DomainResultType
- ], TransportMarshallerExecutor.Result[Result]] =
- transportMarshallerExecutor.arrow(transportMarshaller, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: MixerPipelineResult[Result]
- ): TransportMarshallerExecutor.Inputs[DomainResultType] = {
- val domainMarshallingResults = previousResult.domainMarshallerResults.getOrElse {
- throw InvalidStepStateException(identifier, "DomainMarshallerResults")
- }
-
- // Since the PipelineResult just uses HasMarshalling
- val domainResult = domainMarshallingResults.result.asInstanceOf[DomainResultType]
-
- TransportMarshallerExecutor.Inputs(domainResult)
- }
-
- override def resultUpdater(
- previousPipelineResult: MixerPipelineResult[Result],
- executorResult: TransportMarshallerExecutor.Result[Result]
- ): MixerPipelineResult[Result] = previousPipelineResult.copy(
- transportMarshallerResults = Some(executorResult),
- result = Some(executorResult.result)
- )
- }
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- config: MixerPipelineConfig[Query, DomainResultType, Result]
- ): MixerPipeline[Query, Result] = {
-
- val pipelineIdentifier = config.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val qualityFactorStatus: QualityFactorStatus =
- QualityFactorStatus.build(config.qualityFactorConfigs)
-
- val qualityFactorObserverByPipeline =
- qualityFactorStatus.qualityFactorByPipeline.mapValues { qualityFactor =>
- qualityFactor.buildObserver()
- }
-
- buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver)
-
- val candidatePipelines: Seq[CandidatePipeline[Query]] = config.candidatePipelines.map {
- pipelineConfig: CandidatePipelineConfig[Query, _, _, _] =>
- pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory)
- }
-
- val dependentCandidatePipelines: Seq[CandidatePipeline[Query]] =
- config.dependentCandidatePipelines.map {
- pipelineConfig: DependentCandidatePipelineConfig[Query, _, _, _] =>
- pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory)
- }
-
- val builtSteps = Seq(
- qualityFactorStep(qualityFactorStatus),
- gatesStep(config.gates, context),
- fetchQueryFeaturesStep(
- config.fetchQueryFeatures,
- MixerPipelineConfig.fetchQueryFeaturesStep,
- (previousPipelineResult, executorResult) =>
- previousPipelineResult.copy(queryFeatures = Some(executorResult)),
- context
- ),
- fetchQueryFeaturesStep(
- config.fetchQueryFeaturesPhase2,
- MixerPipelineConfig.fetchQueryFeaturesPhase2Step,
- (previousPipelineResult, executorResult) =>
- previousPipelineResult.copy(
- queryFeaturesPhase2 = Some(executorResult),
- mergedAsyncQueryFeatures = Some(
- previousPipelineResult.queryFeatures
- .getOrElse(throw InvalidStepStateException(
- MixerPipelineConfig.fetchQueryFeaturesPhase2Step,
- "QueryFeatures"))
- .asyncFeatureMap ++ executorResult.asyncFeatureMap)
- ),
- context
- ),
- asyncFeaturesStep(MixerPipelineConfig.candidatePipelinesStep, context),
- candidatePipelinesStep(
- candidatePipelines,
- config.defaultFailOpenPolicy,
- config.failOpenPolicies,
- qualityFactorObserverByPipeline,
- context),
- asyncFeaturesStep(MixerPipelineConfig.dependentCandidatePipelinesStep, context),
- dependentCandidatePipelinesStep(
- dependentCandidatePipelines,
- config.defaultFailOpenPolicy,
- config.failOpenPolicies,
- qualityFactorObserverByPipeline,
- context),
- asyncFeaturesStep(MixerPipelineConfig.resultSelectorsStep, context),
- resultSelectorsStep(config.resultSelectors, context),
- domainMarshallingStep(config.domainMarshaller, context),
- asyncFeaturesStep(MixerPipelineConfig.resultSideEffectsStep, context),
- resultSideEffectsStep(config.resultSideEffects, context),
- transportMarshallingStep(config.transportMarshaller, context)
- )
-
- val finalArrow = buildCombinedArrowFromSteps(
- steps = builtSteps,
- context = context,
- initialEmptyResult = MixerPipelineResult.empty,
- stepsInOrderFromConfig = MixerPipelineConfig.stepsInOrder
- )
-
- val configFromBuilder = config
- new MixerPipeline[Query, Result] {
- override private[core] val config: MixerPipelineConfig[Query, _, Result] = configFromBuilder
- override val arrow: Arrow[Query, MixerPipelineResult[Result]] = finalArrow
- override val identifier: MixerPipelineIdentifier = pipelineIdentifier
- override val alerts: Seq[Alert] = config.alerts
- override val children: Seq[Component] =
- config.gates ++
- config.fetchQueryFeatures ++
- candidatePipelines ++
- dependentCandidatePipelines ++
- config.resultSideEffects ++
- Seq(config.domainMarshaller, config.transportMarshaller)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala
deleted file mode 100644
index 4b8ebacbc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.mixer
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class MixerPipelineBuilderFactory @Inject() (
- candidatePipelineExecutor: CandidatePipelineExecutor,
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- domainMarshallerExecutor: DomainMarshallerExecutor,
- transportMarshallerExecutor: TransportMarshallerExecutor,
- pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory,
- statsReceiver: StatsReceiver) {
- def get[
- Query <: PipelineQuery,
- DomainResultType <: HasMarshalling,
- Result
- ]: MixerPipelineBuilder[Query, DomainResultType, Result] = {
- new MixerPipelineBuilder[Query, DomainResultType, Result](
- candidatePipelineExecutor,
- gateExecutor,
- selectorExecutor,
- queryFeatureHydratorExecutor,
- asyncFeatureMapExecutor,
- domainMarshallerExecutor,
- transportMarshallerExecutor,
- pipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory,
- statsReceiver
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala
deleted file mode 100644
index 238533143..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.mixer
-
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.PipelineConfig
-import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig
-
-/**
- * This is the configuration necessary to generate a Mixer Pipeline. Product code should create a
- * MixerPipelineConfig, and then use a MixerPipelineBuilder to get the final MixerPipeline which can
- * process requests.
- *
- * @tparam Query - The domain model for the query or request
- * @tparam UnmarshalledResultType - The result type of the pipeline, but before marshalling to a wire protocol like URT
- * @tparam Result - The final result that will be served to users
- */
-trait MixerPipelineConfig[Query <: PipelineQuery, UnmarshalledResultType <: HasMarshalling, Result]
- extends PipelineConfig {
-
- override val identifier: MixerPipelineIdentifier
-
- /**
- * Mixer Pipeline Gates will be executed before any other step (including retrieval from candidate
- * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution.
- */
- def gates: Seq[Gate[Query]] = Seq.empty
-
- /**
- * A mixer pipeline can fetch query-level features before candidate pipelines are executed.
- */
- def fetchQueryFeatures: Seq[QueryFeatureHydrator[Query]] = Seq.empty
-
- /**
- * For query-level features that are dependent on query-level features from [[fetchQueryFeatures]]
- */
- def fetchQueryFeaturesPhase2: Seq[QueryFeatureHydrator[Query]] = Seq.empty
-
- /**
- * Candidate pipelines retrieve candidates for possible inclusion in the result
- */
- def candidatePipelines: Seq[CandidatePipelineConfig[Query, _, _, _]]
-
- /**
- * Dependent candidate pipelines to retrieve candidates that depend on the result of [[candidatePipelines]]
- * [[DependentCandidatePipelineConfig]] have access to the list of previously retrieved & decorated
- * candidates for use in constructing the query object.
- */
- def dependentCandidatePipelines: Seq[DependentCandidatePipelineConfig[Query, _, _, _]] = Seq.empty
-
- /**
- * [[defaultFailOpenPolicy]] is the [[FailOpenPolicy]] that will be applied to any candidate
- * pipeline that isn't in the [[failOpenPolicies]] map. By default Candidate Pipelines will fail
- * open for Closed Gates only.
- */
- def defaultFailOpenPolicy: FailOpenPolicy = FailOpenPolicy(Set(ClosedGate))
-
- /**
- * [[failOpenPolicies]] associates [[FailOpenPolicy]]s to specific candidate pipelines using
- * [[CandidatePipelineIdentifier]].
- *
- * @note these [[FailOpenPolicy]]s override the [[defaultFailOpenPolicy]] for a mapped
- * Candidate Pipeline.
- */
- def failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy] = Map.empty
-
- /**
- ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific candidate pipelines
- * using [[CandidatePipelineIdentifier]].
- */
- def qualityFactorConfigs: Map[CandidatePipelineIdentifier, QualityFactorConfig] =
- Map.empty
-
- /**
- * Selectors are executed in sequential order to combine the candidates into a result
- */
- def resultSelectors: Seq[Selector[Query]]
-
- /**
- * Mixer result side effects that are executed after selection and domain marshalling
- */
- def resultSideEffects: Seq[PipelineResultSideEffect[Query, UnmarshalledResultType]] = Seq()
-
- /**
- * Domain marshaller transforms the selections into the model expected by the marshaller
- */
- def domainMarshaller: DomainMarshaller[Query, UnmarshalledResultType]
-
- /**
- * Transport marshaller transforms the model into our line-level API like URT or JSON
- */
- def transportMarshaller: TransportMarshaller[UnmarshalledResultType, Result]
-
- /**
- * A pipeline can define a partial function to rescue failures here. They will be treated as failures
- * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here).
- */
- def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty
-
- /**
- * Alert can be used to indicate the pipeline's service level objectives. Alerts and
- * dashboards will be automatically created based on this information.
- */
- val alerts: Seq[Alert] = Seq.empty
-
- /**
- * This method is used by the product mixer framework to build the pipeline.
- */
- private[core] final def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- builder: MixerPipelineBuilderFactory
- ): MixerPipeline[Query, Result] =
- builder.get.build(parentComponentIdentifierStack, this)
-}
-
-object MixerPipelineConfig extends PipelineConfigCompanion {
- val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor")
- val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates")
- val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures")
- val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier =
- PipelineStepIdentifier("FetchQueryFeaturesPhase2")
- val candidatePipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidatePipelines")
- val dependentCandidatePipelinesStep: PipelineStepIdentifier =
- PipelineStepIdentifier("DependentCandidatePipelines")
- val resultSelectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSelectors")
- val domainMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier("DomainMarshaller")
- val resultSideEffectsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSideEffects")
- val transportMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier(
- "TransportMarshaller")
-
- /** All the Steps which are executed by a [[MixerPipeline]] in the order in which they are run */
- override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq(
- qualityFactorStep,
- gatesStep,
- fetchQueryFeaturesStep,
- fetchQueryFeaturesPhase2Step,
- asyncFeaturesStep(candidatePipelinesStep),
- candidatePipelinesStep,
- asyncFeaturesStep(dependentCandidatePipelinesStep),
- dependentCandidatePipelinesStep,
- asyncFeaturesStep(resultSelectorsStep),
- resultSelectorsStep,
- domainMarshallerStep,
- asyncFeaturesStep(resultSideEffectsStep),
- resultSideEffectsStep,
- transportMarshallerStep
- )
-
- /**
- * All the Steps which an [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator AsyncHydrator]]
- * can be configured to [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator.hydrateBefore hydrateBefore]]
- */
- override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set(
- candidatePipelinesStep,
- dependentCandidatePipelinesStep,
- resultSelectorsStep,
- resultSideEffectsStep
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala
deleted file mode 100644
index 1ddf00bd4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.mixer
-
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-
-/**
- * A [[MixerPipelineResult]] includes both the user-visible [[PipelineResult]] and all the
- * Execution details possible - intermediate results, what components did, etc.
- */
-case class MixerPipelineResult[Result](
- qualityFactorResult: Option[QualityFactorExecutorResult],
- gateResult: Option[GateExecutorResult],
- queryFeatures: Option[QueryFeatureHydratorExecutor.Result],
- queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result],
- mergedAsyncQueryFeatures: Option[AsyncFeatureMap],
- candidatePipelineResults: Option[CandidatePipelineExecutorResult],
- dependentCandidatePipelineResults: Option[CandidatePipelineExecutorResult],
- resultSelectorResults: Option[SelectorExecutorResult],
- domainMarshallerResults: Option[DomainMarshallerExecutor.Result[HasMarshalling]],
- resultSideEffectResults: Option[PipelineResultSideEffectExecutor.Result],
- asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults],
- transportMarshallerResults: Option[TransportMarshallerExecutor.Result[Result]],
- failure: Option[PipelineFailure],
- result: Option[Result])
- extends PipelineResult[Result] {
-
- override def withFailure(failure: PipelineFailure): PipelineResult[Result] =
- copy(failure = Some(failure))
-
- override def withResult(result: Result): PipelineResult[Result] = copy(result = Some(result))
-
- /**
- * resultSize is calculated based on the selector results rather than the marshalled results. The
- * structure of the marshalled format is unknown, making operating on selector results more
- * convenient. This will implicitly excluded cursors built during marshalling but cursors don't
- * contribute to the result size anyway.
- */
- override val resultSize: Int =
- resultSelectorResults.map(_.selectedCandidates).map(PipelineResult.resultSize).getOrElse(0)
-}
-
-object MixerPipelineResult {
- def empty[A]: MixerPipelineResult[A] = MixerPipelineResult(
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD
deleted file mode 100644
index 68dfa5b8f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala
deleted file mode 100644
index eef0db9b4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.pipeline_failure
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import scala.util.control.NoStackTrace
-
-/**
- * Pipeline Failures represent pipeline requests that were not able to complete.
- *
- * A pipeline result will always define either a result or a failure.
- *
- * The reason field should not be displayed to end-users, and is free to change over time.
- * It should always be free of private user data such that we can log it.
- *
- * The pipeline can classify it's own failures into categories (timeouts, invalid arguments,
- * rate limited, etc) such that the caller can choose how to handle it.
- *
- * @note [[componentStack]] should only be set by the product mixer framework,
- * it should **NOT** be set when making a [[PipelineFailure]]
- */
-@JsonSerialize(using = classOf[PipelineFailureSerializer])
-case class PipelineFailure(
- category: PipelineFailureCategory,
- reason: String,
- underlying: Option[Throwable] = None,
- componentStack: Option[ComponentIdentifierStack] = None)
- extends Exception(
- "PipelineFailure(" +
- s"category = $category, " +
- s"reason = $reason, " +
- s"underlying = $underlying, " +
- s"componentStack = $componentStack)",
- underlying.orNull
- ) {
- override def toString: String = getMessage
-
- /** Returns an updated copy of this [[PipelineFailure]] with the same exception stacktrace */
- def copy(
- category: PipelineFailureCategory = this.category,
- reason: String = this.reason,
- underlying: Option[Throwable] = this.underlying,
- componentStack: Option[ComponentIdentifierStack] = this.componentStack
- ): PipelineFailure = {
- val newPipelineFailure =
- new PipelineFailure(category, reason, underlying, componentStack) with NoStackTrace
- newPipelineFailure.setStackTrace(this.getStackTrace)
- newPipelineFailure
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala
deleted file mode 100644
index f0cb57fe0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.pipeline_failure
-
-/**
- * Failures are grouped into categories based on which party is 'responsible' for the issue. This
- * is important for generating accurate SLOs and ensuring that the correct team is alerted.
- */
-sealed trait PipelineFailureCategory {
- val categoryName: String
- val failureName: String
-}
-
-/**
- * Client Failures are failures where the client is deemed responsible for the issue. Such as by
- * issuing an invalid request or not having the right permissions.
- *
- * A failure might belong in this category if it relates to behaviour on the client and is not
- * actionable by the team which owns the product.
- */
-trait ClientFailure extends PipelineFailureCategory {
- override val categoryName: String = "ClientFailure"
-}
-
-/**
- * The requested product is disabled so the request cannot be served.
- */
-case object ProductDisabled extends ClientFailure {
- override val failureName: String = "ProductDisabled"
-}
-
-/**
- * The request was deemed invalid by this or a backing service.
- */
-case object BadRequest extends ClientFailure {
- override val failureName: String = "BadRequest"
-}
-
-/**
- * Credentials proving the identity of the caller were missing, not trusted, or expired.
- * For example, an auth cookie might be expired and in need of refreshing.
- *
- * Do not confuse this with Authorization, where the credentials are believed but not allowed to perform the operation.
- */
-case object Authentication extends ClientFailure {
- override val failureName: String = "Authentication"
-}
-
-/**
- * The operation was forbidden (often, but not always, by a Strato access control policy).
- *
- * Do not confuse this with Authentication, where the given credentials were missing, not trusted, or expired.
- */
-case object Unauthorized extends ClientFailure {
- override val failureName: String = "Unauthorized"
-}
-
-/**
- * The operation returned a Not Found response.
- */
-case object NotFound extends ClientFailure {
- override val failureName: String = "NotFound"
-}
-
-/**
- * An invalid input is included in a cursor field.
- */
-case object MalformedCursor extends ClientFailure {
- override val failureName: String = "MalformedCursor"
-}
-
-/**
- * The operation did not succeed due to a closed gate
- */
-case object ClosedGate extends ClientFailure {
- override val failureName: String = "ClosedGate"
-}
-
-/**
- * Server Failures are failures for which the owner of the product is responsible. Typically this
- * means the request was valid but an issue within Product Mixer or a dependent service prevented
- * it from succeeding.
- *
- * Server Failures contribute to the success rate SLO for the product.
- */
-trait ServerFailure extends PipelineFailureCategory {
- override val categoryName: String = "ServerFailure"
-}
-
-/**
- * Unclassified failures occur when product code throws an exception that Product Mixer does not
- * know how to classify.
- *
- * They can be used in failOpen policies, etc - but it's always preferred to instead add additional
- * classification logic and to keep Unclassified failures at 0.
- */
-case object UncategorizedServerFailure extends ServerFailure {
- override val failureName: String = "UncategorizedServerFailure"
-}
-
-/**
- * A hydrator or transformer returned a misconfigured feature map, this indicates a customer
- * configuration error. The owner of the component should make sure the hydrator always returns a
- * [[FeatureMap]] with the all features defined in the hydrator also set in the map, it should not have
- * any unregistered features nor should registered features be absent.
- */
-case object MisconfiguredFeatureMapFailure extends ServerFailure {
- override val failureName: String = "MisconfiguredFeatureMapFailure"
-}
-
-/**
- * A PipelineSelector returned an invalid ComponentIdentifier.
- *
- * A pipeline selector should choose the identifier of a pipeline that is contained by the 'pipelines'
- * sequence of the ProductPipelineConfig.
- */
-case object InvalidPipelineSelected extends ServerFailure {
- override val failureName: String = "InvalidPipelineSelected"
-}
-
-/**
- * Failures that occur when product code reaches an unexpected or otherwise illegal state.
- */
-case object IllegalStateFailure extends ServerFailure {
- override val failureName: String = "IllegalStateFailure"
-}
-
-/**
- * An unexpected candidate was returned in a candidate source that was unable to be transformed.
- */
-case object UnexpectedCandidateResult extends ServerFailure {
- override val failureName: String = "UnexpectedCandidateResult"
-}
-
-/**
- * An unexpected Candidate was returned in a marshaller
- */
-case object UnexpectedCandidateInMarshaller extends ServerFailure {
- override val failureName: String = "UnexpectedCandidateInMarshaller"
-}
-
-/**
- * Pipeline execution failed due to an incorrectly configured quality factor (e.g, accessing
- * quality factor state for a pipeline that does not have quality factor configured)
- */
-case object MisconfiguredQualityFactor extends ServerFailure {
- override val failureName: String = "MisconfiguredQualityFactor"
-}
-
-/**
- * Pipeline execution failed due to an incorrectly configured decorator (e.g, decorator
- * returned the wrong type or tried to decorate an already decorated candidate)
- */
-case object MisconfiguredDecorator extends ServerFailure {
- override val failureName: String = "MisconfiguredDecorator"
-}
-
-/**
- * Candidate Source Pipeline execution failed due to a timeout.
- */
-case object CandidateSourceTimeout extends ServerFailure {
- override val failureName: String = "CandidateSourceTimeout"
-}
-
-/**
- * Platform Failures are issues in the core Product Mixer logic itself which prevent a pipeline from
- * properly executing. These failures are the responsibility of the Product Mixer team.
- */
-trait PlatformFailure extends PipelineFailureCategory {
- override val categoryName: String = "PlatformFailure"
-}
-
-/**
- * Pipeline execution failed due to an unexpected error in Product Mixer.
- *
- * ExecutionFailed indicates a bug with the core Product Mixer execution logic rather than with a
- * specific product. For example, a bug in PipelineBuilder leading to us returning a
- * ProductPipelineResult that neither succeeded nor failed.
- */
-case object ExecutionFailed extends PlatformFailure {
- override val failureName: String = "ExecutionFailed"
-}
-
-/**
- * Pipeline execution failed due to a feature hydration failure.
- *
- * FeatureHydrationFailed indicates that the underlying hydration for a feature defined in a hydrator
- * failed (e.g, typically from a RPC call failing).
- */
-case object FeatureHydrationFailed extends PlatformFailure {
- override val failureName: String = "FeatureHydrationFailed"
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala
deleted file mode 100644
index 449542ba9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.pipeline_failure
-
-/** Represents a way to classify a given [[Throwable]] to a [[PipelineFailure]] */
-case class PipelineFailureClassifier(
- classifier: PartialFunction[Throwable, PipelineFailure])
- extends PartialFunction[Throwable, PipelineFailure] {
- override def isDefinedAt(throwable: Throwable): Boolean = classifier.isDefinedAt(throwable)
- override def apply(throwable: Throwable): PipelineFailure = classifier.apply(throwable)
-}
-
-private[core] object PipelineFailureClassifier {
- val Empty: PipelineFailureClassifier = PipelineFailureClassifier(PartialFunction.empty)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala
deleted file mode 100644
index 9e4607b4c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.pipeline_failure
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-
-private[pipeline_failure] class PipelineFailureSerializer()
- extends JsonSerializer[PipelineFailure] {
-
- private sealed trait BaseSerializableException
-
- private case class SerializableException(
- `class`: String,
- message: String,
- stackTrace: Seq[String],
- cause: Option[BaseSerializableException])
- extends BaseSerializableException
-
- private case class SerializablePipelineFailure(
- category: String,
- reason: String,
- underlying: Option[BaseSerializableException],
- componentStack: Option[ComponentIdentifierStack],
- stackTrace: Seq[String])
- extends BaseSerializableException
-
- private def serializeStackTrace(stackTrace: Array[StackTraceElement]): Seq[String] =
- stackTrace.map(stackTraceElement => "at " + stackTraceElement.toString)
-
- private def mkSerializableException(
- t: Throwable,
- recursionDepth: Int = 0
- ): Option[BaseSerializableException] = {
- t match {
- case _ if recursionDepth > 4 =>
- // in the unfortunate case of a super deep chain of exceptions, stop if we get too deep
- None
- case pipelineFailure: PipelineFailure =>
- Some(
- SerializablePipelineFailure(
- category =
- pipelineFailure.category.categoryName + "/" + pipelineFailure.category.failureName,
- reason = pipelineFailure.reason,
- underlying =
- pipelineFailure.underlying.flatMap(mkSerializableException(_, recursionDepth + 1)),
- componentStack = pipelineFailure.componentStack,
- stackTrace = serializeStackTrace(pipelineFailure.getStackTrace)
- ))
- case t =>
- Some(
- SerializableException(
- `class` = t.getClass.getName,
- message = t.getMessage,
- stackTrace = serializeStackTrace(t.getStackTrace),
- cause = Option(t.getCause).flatMap(mkSerializableException(_, recursionDepth + 1))
- )
- )
- }
- }
-
- override def serialize(
- pipelineFailure: PipelineFailure,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit = serializers.defaultSerializeValue(mkSerializableException(pipelineFailure), gen)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD
deleted file mode 100644
index 6a1c78097..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD
+++ /dev/null
@@ -1,51 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client",
- "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/stitch",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala
deleted file mode 100644
index 407379234..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.product_mixer.core.functional_component.common.access_policy.WithDebugAccessPolicies
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.stitch.Arrow
-
-/**
- * A Product Pipeline
- *
- * This is an abstract class, as we only construct these via the [[ProductPipelineBuilder]].
- *
- * A [[ProductPipeline]] is capable of processing a [[Request]] and returning a response.
- *
- * @tparam RequestType the domain model for the query or request
- * @tparam ResponseType the final marshalled result type
- */
-abstract class ProductPipeline[RequestType <: Request, ResponseType] private[product]
- extends Pipeline[ProductPipelineRequest[RequestType], ResponseType]
- with WithDebugAccessPolicies {
- override private[core] val config: ProductPipelineConfig[RequestType, _, ResponseType]
- override val arrow: Arrow[
- ProductPipelineRequest[RequestType],
- ProductPipelineResult[ResponseType]
- ]
- override val identifier: ProductPipelineIdentifier
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala
deleted file mode 100644
index 600a70eed..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala
+++ /dev/null
@@ -1,385 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finagle.tracing.Trace
-import com.twitter.finagle.transport.Transport
-import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.gate.DenyLoggedOutUsersGate
-import com.twitter.product_mixer.core.gate.ParamGate
-import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix
-import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.InvalidStepStateException
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineConfig
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineConfig
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineResult
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorRequest
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorResult
-import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutor
-import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutorResult
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-import com.twitter.stitch.Arrow
-import com.twitter.stringcenter.client.StringCenterRequestContext
-import com.twitter.stringcenter.client.stitch.StringCenterRequestContextLetter
-import com.twitter.timelines.configapi.Params
-import com.twitter.util.logging.Logging
-import org.slf4j.MDC
-
-class ProductPipelineBuilder[TRequest <: Request, Query <: PipelineQuery, Response](
- gateExecutor: GateExecutor,
- pipelineSelectorExecutor: PipelineSelectorExecutor,
- pipelineExecutor: PipelineExecutor,
- mixerPipelineBuilderFactory: MixerPipelineBuilderFactory,
- recommendationPipelineBuilderFactory: RecommendationPipelineBuilderFactory,
- override val statsReceiver: StatsReceiver,
- pipelineExecutionLogger: PipelineExecutionLogger)
- extends PipelineBuilder[ProductPipelineRequest[TRequest]]
- with Logging { builder =>
-
- override type UnderlyingResultType = Response
- override type PipelineResultType = ProductPipelineResult[Response]
-
- /**
- * Query Transformer Step is implemented inline instead of using an executor.
- *
- * It's a simple, synchronous step that executes the query transformer.
- *
- * Since the output of the transformer is used in multiple other steps (Gate, Pipeline Execution),
- * we've promoted the transformer to a step so that it's outputs can be reused easily.
- */
- def pipelineQueryTransformerStep(
- queryTransformer: (TRequest, Params) => Query,
- context: Executor.Context
- ): Step[ProductPipelineRequest[TRequest], Query] =
- new Step[ProductPipelineRequest[TRequest], Query] {
-
- override def identifier: PipelineStepIdentifier =
- ProductPipelineConfig.pipelineQueryTransformerStep
-
- override def executorArrow: Arrow[ProductPipelineRequest[TRequest], Query] = {
- wrapWithErrorHandling(context, identifier)(
- Arrow.map[ProductPipelineRequest[TRequest], Query] {
- case ProductPipelineRequest(request, params) => queryTransformer(request, params)
- }
- )
- }
-
- override def inputAdaptor(
- query: ProductPipelineRequest[TRequest],
- previousResult: ProductPipelineResult[Response]
- ): ProductPipelineRequest[TRequest] = query
-
- override def resultUpdater(
- previousPipelineResult: ProductPipelineResult[Response],
- executorResult: Query
- ): ProductPipelineResult[Response] =
- previousPipelineResult.copy(transformedQuery = Some(executorResult))
- }
-
- def qualityFactorStep(
- qualityFactorStatus: QualityFactorStatus
- ): Step[Query, QualityFactorExecutorResult] = {
- new Step[Query, QualityFactorExecutorResult] {
- override def identifier: PipelineStepIdentifier = ProductPipelineConfig.qualityFactorStep
-
- override def executorArrow: Arrow[Query, QualityFactorExecutorResult] =
- Arrow
- .map[Query, QualityFactorExecutorResult] { _ =>
- QualityFactorExecutorResult(
- pipelineQualityFactors =
- qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue)
- )
- }
-
- override def inputAdaptor(
- query: ProductPipelineRequest[TRequest],
- previousResult: ProductPipelineResult[Response]
- ): Query = previousResult.transformedQuery
- .getOrElse {
- throw InvalidStepStateException(identifier, "TransformedQuery")
- }.asInstanceOf[Query]
-
- override def resultUpdater(
- previousPipelineResult: ProductPipelineResult[Response],
- executorResult: QualityFactorExecutorResult
- ): ProductPipelineResult[Response] = {
- previousPipelineResult.copy(
- transformedQuery = previousPipelineResult.transformedQuery.map {
- case queryWithQualityFactor: HasQualityFactorStatus =>
- queryWithQualityFactor
- .withQualityFactorStatus(qualityFactorStatus).asInstanceOf[Query]
- case query =>
- query
- },
- qualityFactorResult = Some(executorResult)
- )
- }
- }
- }
-
- def gatesStep(
- gates: Seq[Gate[Query]],
- context: Executor.Context
- ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] {
- override def identifier: PipelineStepIdentifier = ProductPipelineConfig.gatesStep
-
- override def executorArrow: Arrow[Query, GateExecutorResult] = {
- gateExecutor.arrow(gates, context)
- }
-
- override def inputAdaptor(
- query: ProductPipelineRequest[TRequest],
- previousResult: ProductPipelineResult[Response]
- ): Query = previousResult.transformedQuery
- .getOrElse {
- throw InvalidStepStateException(identifier, "TransformedQuery")
- }.asInstanceOf[Query]
-
- override def resultUpdater(
- previousPipelineResult: ProductPipelineResult[Response],
- executorResult: GateExecutorResult
- ): ProductPipelineResult[Response] =
- previousPipelineResult.copy(gateResult = Some(executorResult))
- }
-
- def pipelineSelectorStep(
- pipelineByIdentifer: Map[ComponentIdentifier, Pipeline[Query, Response]],
- pipelineSelector: Query => ComponentIdentifier,
- context: Executor.Context
- ): Step[Query, PipelineSelectorExecutorResult] =
- new Step[Query, PipelineSelectorExecutorResult] {
- override def identifier: PipelineStepIdentifier = ProductPipelineConfig.pipelineSelectorStep
-
- override def executorArrow: Arrow[
- Query,
- PipelineSelectorExecutorResult
- ] = pipelineSelectorExecutor.arrow(pipelineByIdentifer, pipelineSelector, context)
-
- override def inputAdaptor(
- query: ProductPipelineRequest[TRequest],
- previousResult: ProductPipelineResult[Response]
- ): Query =
- previousResult.transformedQuery
- .getOrElse(throw InvalidStepStateException(identifier, "TransformedQuery")).asInstanceOf[
- Query]
-
- override def resultUpdater(
- previousPipelineResult: ProductPipelineResult[Response],
- executorResult: PipelineSelectorExecutorResult
- ): ProductPipelineResult[Response] =
- previousPipelineResult.copy(pipelineSelectorResult = Some(executorResult))
- }
-
- def pipelineExecutionStep(
- pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Step[PipelineExecutorRequest[Query], PipelineExecutorResult[Response]] =
- new Step[PipelineExecutorRequest[Query], PipelineExecutorResult[Response]] {
- override def identifier: PipelineStepIdentifier = ProductPipelineConfig.pipelineExecutionStep
-
- override def executorArrow: Arrow[
- PipelineExecutorRequest[Query],
- PipelineExecutorResult[Response]
- ] = {
- pipelineExecutor.arrow(pipelineByIdentifier, qualityFactorObserverByPipeline, context)
- }
-
- override def inputAdaptor(
- request: ProductPipelineRequest[TRequest],
- previousResult: ProductPipelineResult[Response]
- ): PipelineExecutorRequest[Query] = {
- val query = previousResult.transformedQuery
- .getOrElse {
- throw InvalidStepStateException(identifier, "TransformedQuery")
- }.asInstanceOf[Query]
-
- val pipelineIdentifier = previousResult.pipelineSelectorResult
- .map(_.pipelineIdentifier).getOrElse {
- throw InvalidStepStateException(identifier, "PipelineSelectorResult")
- }
-
- PipelineExecutorRequest(query, pipelineIdentifier)
- }
-
- override def resultUpdater(
- previousPipelineResult: ProductPipelineResult[Response],
- executorResult: PipelineExecutorResult[Response]
- ): ProductPipelineResult[Response] = {
-
- val mixerPipelineResult = executorResult.pipelineResult match {
- case mixerPipelineResult: MixerPipelineResult[Response] @unchecked =>
- Some(mixerPipelineResult)
- case _ =>
- None
- }
-
- val recommendationPipelineResult = executorResult.pipelineResult match {
- case recommendationPipelineResult: RecommendationPipelineResult[
- _,
- Response
- ] @unchecked =>
- Some(recommendationPipelineResult)
- case _ =>
- None
- }
-
- previousPipelineResult.copy(
- mixerPipelineResult = mixerPipelineResult,
- recommendationPipelineResult = recommendationPipelineResult,
- traceId = Trace.idOption.map(_.traceId.toString()),
- result = executorResult.pipelineResult.result
- )
- }
- }
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- config: ProductPipelineConfig[TRequest, Query, Response]
- ): ProductPipeline[TRequest, Response] = {
-
- val pipelineIdentifier = config.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val denyLoggedOutUsersGate = if (config.denyLoggedOutUsers) {
- Some(DenyLoggedOutUsersGate(pipelineIdentifier))
- } else {
- None
- }
- val enabledGate: ParamGate =
- ParamGate(pipelineIdentifier + EnabledGateSuffix, config.paramConfig.EnabledDeciderParam)
- val supportedClientGate =
- ParamGate(
- pipelineIdentifier + SupportedClientGateSuffix,
- config.paramConfig.SupportedClientParam)
-
- /**
- * Evaluate enabled decider gate first since if it's off, there is no reason to proceed
- * Next evaluate supported client feature switch gate, followed by customer configured gates
- */
- val allGates =
- denyLoggedOutUsersGate.toSeq ++: enabledGate +: supportedClientGate +: config.gates
-
- val childPipelines: Seq[Pipeline[Query, Response]] =
- config.pipelines.map {
- case mixerConfig: MixerPipelineConfig[Query, _, Response] =>
- mixerConfig.build(context.componentStack, mixerPipelineBuilderFactory)
- case recommendationConfig: RecommendationPipelineConfig[Query, _, _, Response] =>
- recommendationConfig.build(context.componentStack, recommendationPipelineBuilderFactory)
- case other =>
- throw new IllegalArgumentException(
- s"Product Pipelines only support Mixer and Recommendation pipelines, not $other")
- }
-
- val pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]] =
- childPipelines.map { pipeline =>
- (pipeline.identifier, pipeline)
- }.toMap
-
- val qualityFactorStatus: QualityFactorStatus =
- QualityFactorStatus.build(config.qualityFactorConfigs)
-
- val qualityFactorObserverByPipeline = qualityFactorStatus.qualityFactorByPipeline.mapValues {
- qualityFactor =>
- qualityFactor.buildObserver()
- }
-
- buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver)
-
- /**
- * Initialize MDC with access logging with everything we have at request time. We can put
- * more stuff into MDC later down the pipeline, but at risk of exceptions/errors preventing
- * them from being added
- */
- val mdcInitArrow =
- Arrow.map[ProductPipelineRequest[TRequest], ProductPipelineRequest[TRequest]] { request =>
- val serviceIdentifier = ServiceIdentifier.fromCertificate(Transport.peerCertificate)
- MDC.put("product", config.product.identifier.name)
- MDC.put("serviceIdentifier", ServiceIdentifier.asString(serviceIdentifier))
- request
- }
-
- val builtSteps = Seq(
- pipelineQueryTransformerStep(config.pipelineQueryTransformer, context),
- qualityFactorStep(qualityFactorStatus),
- gatesStep(allGates, context),
- pipelineSelectorStep(pipelineByIdentifier, config.pipelineSelector, context),
- pipelineExecutionStep(pipelineByIdentifier, qualityFactorObserverByPipeline, context)
- )
-
- val underlying: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] =
- buildCombinedArrowFromSteps(
- steps = builtSteps,
- context = context,
- initialEmptyResult = ProductPipelineResult.empty,
- stepsInOrderFromConfig = ProductPipelineConfig.stepsInOrder
- )
-
- /**
- * Unlike other components and pipelines, [[ProductPipeline]] must be observed in the
- * [[ProductPipelineBuilder]] directly because the resulting [[ProductPipeline.arrow]]
- * is run directly without an executor so must contain all stats.
- */
- val observed =
- wrapProductPipelineWithExecutorBookkeeping[
- ProductPipelineRequest[TRequest],
- ProductPipelineResult[Response]
- ](context, pipelineIdentifier)(underlying)
-
- val finalArrow: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] =
- Arrow
- .letWithArg[
- ProductPipelineRequest[TRequest],
- ProductPipelineResult[Response],
- StringCenterRequestContext](StringCenterRequestContextLetter)(request =>
- StringCenterRequestContext(
- request.request.clientContext.languageCode,
- request.request.clientContext.countryCode
- ))(
- mdcInitArrow
- .andThen(observed)
- .onSuccess(result => result.transformedQuery.map(pipelineExecutionLogger(_, result))))
-
- val configFromBuilder = config
- new ProductPipeline[TRequest, Response] {
- override private[core] val config: ProductPipelineConfig[TRequest, _, Response] =
- configFromBuilder
- override val arrow: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] =
- finalArrow
- override val identifier: ProductPipelineIdentifier = pipelineIdentifier
- override val alerts: Seq[Alert] = config.alerts
- override val debugAccessPolicies: Set[AccessPolicy] = config.debugAccessPolicies
- override val children: Seq[Component] = allGates ++ childPipelines
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala
deleted file mode 100644
index 9e609ed92..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineBuilderFactory
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor
-import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutor
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ProductPipelineBuilderFactory @Inject() (
- gateExecutor: GateExecutor,
- pipelineSelectorExecutor: PipelineSelectorExecutor,
- pipelineExecutor: PipelineExecutor,
- mixerPipelineBuilderFactory: MixerPipelineBuilderFactory,
- recommendationPipelineBuilderFactory: RecommendationPipelineBuilderFactory,
- statsReceiver: StatsReceiver,
- pipelineExecutionLogger: PipelineExecutionLogger) {
- def get[
- TRequest <: Request,
- Query <: PipelineQuery,
- Response
- ]: ProductPipelineBuilder[TRequest, Query, Response] = {
- new ProductPipelineBuilder[TRequest, Query, Response](
- gateExecutor,
- pipelineSelectorExecutor,
- pipelineExecutor,
- mixerPipelineBuilderFactory,
- recommendationPipelineBuilderFactory,
- statsReceiver,
- pipelineExecutionLogger
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala
deleted file mode 100644
index ade9b76a8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.PipelineConfig
-import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.product.ProductParamConfig
-import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig
-import com.twitter.timelines.configapi.Params
-
-trait ProductPipelineConfig[TRequest <: Request, Query <: PipelineQuery, Response]
- extends PipelineConfig {
-
- override val identifier: ProductPipelineIdentifier
-
- val product: Product
- val paramConfig: ProductParamConfig
-
- /**
- * Product Pipeline Gates will be executed before any other step (including retrieval from mixer
- * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution.
- */
- def gates: Seq[Gate[Query]] = Seq.empty
-
- def pipelineQueryTransformer(request: TRequest, params: Params): Query
-
- /**
- * A list of all pipelines that power this product directly (there is no need to include pipelines
- * called by those pipelines).
- *
- * Only pipeline from this list should referenced from the pipelineSelector
- */
- def pipelines: Seq[PipelineConfig]
-
- /**
- * A pipeline selector selects a pipeline (from the list in `def pipelines`) to handle the
- * current request.
- */
- def pipelineSelector(query: Query): ComponentIdentifier
-
- /**
- ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific pipelines
- * using [[ComponentIdentifier]].
- */
- def qualityFactorConfigs: Map[ComponentIdentifier, QualityFactorConfig] =
- Map.empty
-
- /**
- * By default (for safety), product mixer pipelines do not allow logged out requests.
- * A "DenyLoggedOutUsersGate" will be generated and added to the pipeline.
- *
- * You can disable this behavior by overriding `denyLoggedOutUsers` with False.
- */
- val denyLoggedOutUsers: Boolean = true
-
- /**
- * A pipeline can define a partial function to rescue failures here. They will be treated as failures
- * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here).
- */
- def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty
-
- /**
- * Alerts can be used to indicate the pipeline's service level objectives. Alerts and
- * dashboards will be automatically created based on this information.
- */
- val alerts: Seq[Alert] = Seq.empty
-
- /**
- * Access Policies can be used to gate who can query a product from Product Mixer's query tool
- * (go/turntable).
- *
- * This will typically be gated by an LDAP group associated with your team. For example:
- *
- * {{{
- * override val debugAccessPolicies: Set[AccessPolicy] = Set(AllowedLdapGroups("NAME"))
- * }}}
- *
- * You can disable all queries by using the [[com.twitter.product_mixer.core.functional_component.common.access_policy.BlockEverything]] policy.
- */
- val debugAccessPolicies: Set[AccessPolicy]
-}
-
-object ProductPipelineConfig extends PipelineConfigCompanion {
- val pipelineQueryTransformerStep: PipelineStepIdentifier = PipelineStepIdentifier(
- "PipelineQueryTransformer")
- val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor")
- val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates")
- val pipelineSelectorStep: PipelineStepIdentifier = PipelineStepIdentifier("PipelineSelector")
- val pipelineExecutionStep: PipelineStepIdentifier = PipelineStepIdentifier("PipelineExecution")
-
- /** All the Steps which are executed by a [[ProductPipeline]] in the order in which they are run */
- override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq(
- pipelineQueryTransformerStep,
- qualityFactorStep,
- gatesStep,
- pipelineSelectorStep,
- pipelineExecutionStep
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala
deleted file mode 100644
index 7cefde3d7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.timelines.configapi.Params
-
-case class ProductPipelineRequest[RequestType](request: RequestType, params: Params)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala
deleted file mode 100644
index c0065992a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.product
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutorResult
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-
-case class ProductPipelineResult[Result](
- transformedQuery: Option[PipelineQuery],
- qualityFactorResult: Option[QualityFactorExecutorResult],
- gateResult: Option[GateExecutorResult],
- pipelineSelectorResult: Option[PipelineSelectorExecutorResult],
- mixerPipelineResult: Option[MixerPipelineResult[Result]],
- recommendationPipelineResult: Option[RecommendationPipelineResult[_, Result]],
- traceId: Option[String],
- failure: Option[PipelineFailure],
- result: Option[Result])
- extends PipelineResult[Result] {
-
- override val resultSize: Int = {
- if (mixerPipelineResult.isDefined) {
- mixerPipelineResult.map(_.resultSize).getOrElse(0)
- } else {
- recommendationPipelineResult.map(_.resultSize).getOrElse(0)
- }
- }
-
- override def withFailure(failure: PipelineFailure): PipelineResult[Result] =
- copy(failure = Some(failure))
-
- override def withResult(result: Result): PipelineResult[Result] = copy(result = Some(result))
-}
-
-object ProductPipelineResult {
- def empty[A]: ProductPipelineResult[A] = ProductPipelineResult(
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None
- )
-
- def fromResult[A](result: A): ProductPipelineResult[A] = ProductPipelineResult(
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- Some(result)
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD
deleted file mode 100644
index 506e537c1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD
+++ /dev/null
@@ -1,62 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector:insert_append_results",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala
deleted file mode 100644
index fe379c9b9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.recommendation
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Arrow
-
-/**
- * A Recommendation Pipeline
- *
- * This is an abstract class, as we only construct these via the [[RecommendationPipelineBuilder]].
- *
- * A [[RecommendationPipeline]] is capable of processing requests (queries) and returning responses (results)
- * in the correct format to directly send to users.
- *
- * @tparam Query the domain model for the query or request
- * @tparam Candidate the type of the candidates
- * @tparam Result the final marshalled result type
- */
-abstract class RecommendationPipeline[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- Result]
- extends Pipeline[Query, Result] {
- override private[core] val config: RecommendationPipelineConfig[Query, Candidate, _, Result]
- override val arrow: Arrow[Query, RecommendationPipelineResult[Candidate, Result]]
- override val identifier: RecommendationPipelineIdentifier
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala
deleted file mode 100644
index 684ec3c6d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala
+++ /dev/null
@@ -1,1076 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.recommendation
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.util.logging.Logging
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.InvalidStepStateException
-import com.twitter.product_mixer.core.pipeline.PipelineBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredDecorator
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineConfig
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor
-import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutorResult
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-import com.twitter.stitch.Arrow
-
-/**
- * RecommendationPipelineBuilder builds [[RecommendationPipeline]]s from [[RecommendationPipelineConfig]]s.
- *
- * You should inject a [[RecommendationPipelineBuilderFactory]] and call `.get` to build these.
- *
- * @see [[RecommendationPipelineConfig]] for the description of the type parameters.
- *
- * @note Almost a mirror of MixerPipelineBuilder
- */
-
-class RecommendationPipelineBuilder[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- DomainResultType <: HasMarshalling,
- Result
-](
- candidatePipelineExecutor: CandidatePipelineExecutor,
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- filterExecutor: FilterExecutor,
- scoringPipelineExecutor: ScoringPipelineExecutor,
- candidateDecoratorExecutor: CandidateDecoratorExecutor,
- domainMarshallerExecutor: DomainMarshallerExecutor,
- transportMarshallerExecutor: TransportMarshallerExecutor,
- pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory,
- scoringPipelineBuilderFactory: ScoringPipelineBuilderFactory,
- override val statsReceiver: StatsReceiver)
- extends PipelineBuilder[Query]
- with Logging {
-
- override type UnderlyingResultType = Result
- override type PipelineResultType = RecommendationPipelineResult[Candidate, Result]
-
- def qualityFactorStep(
- qualityFactorStatus: QualityFactorStatus
- ): Step[Query, QualityFactorExecutorResult] =
- new Step[Query, QualityFactorExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.qualityFactorStep
-
- override def executorArrow: Arrow[Query, QualityFactorExecutorResult] =
- Arrow
- .map[Query, QualityFactorExecutorResult] { _ =>
- QualityFactorExecutorResult(
- pipelineQualityFactors =
- qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue)
- )
- }
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Query = query
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: QualityFactorExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(qualityFactorResult = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: QualityFactorExecutorResult
- ): Query = {
- query match {
- case queryWithQualityFactor: HasQualityFactorStatus =>
- queryWithQualityFactor
- .withQualityFactorStatus(
- queryWithQualityFactor.qualityFactorStatus.getOrElse(QualityFactorStatus.empty) ++
- qualityFactorStatus
- ).asInstanceOf[Query]
- case _ =>
- query
- }
- }
- }
-
- def gatesStep(
- gates: Seq[Gate[Query]],
- context: Executor.Context
- ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] {
- override def identifier: PipelineStepIdentifier = RecommendationPipelineConfig.gatesStep
-
- override def executorArrow: Arrow[Query, GateExecutorResult] =
- gateExecutor.arrow(gates, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Query =
- query
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: GateExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(gateResult = Some(executorResult))
- }
-
- def fetchQueryFeaturesStep(
- queryFeatureHydrators: Seq[BaseQueryFeatureHydrator[Query, _]],
- stepIdentifier: PipelineStepIdentifier,
- updater: ResultUpdater[
- RecommendationPipelineResult[Candidate, Result],
- QueryFeatureHydratorExecutor.Result
- ],
- context: Executor.Context
- ): Step[Query, QueryFeatureHydratorExecutor.Result] =
- new Step[Query, QueryFeatureHydratorExecutor.Result] {
- override def identifier: PipelineStepIdentifier = stepIdentifier
-
- override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] =
- queryFeatureHydratorExecutor.arrow(
- queryFeatureHydrators,
- RecommendationPipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy,
- context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Query = query
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: QueryFeatureHydratorExecutor.Result
- ): RecommendationPipelineResult[Candidate, Result] =
- updater(previousPipelineResult, executorResult)
-
- override def queryUpdater(
- query: Query,
- executorResult: QueryFeatureHydratorExecutor.Result
- ): Query =
- query
- .withFeatureMap(
- query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query]
- }
-
- def asyncFeaturesStep(
- stepToHydrateFor: PipelineStepIdentifier,
- context: Executor.Context
- ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.asyncFeaturesStep(stepToHydrateFor)
-
- override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- asyncFeatureMapExecutor.arrow(
- stepToHydrateFor,
- identifier,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): AsyncFeatureMap =
- previousResult.mergedAsyncQueryFeatures
- .getOrElse(
- throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures")
- )
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: AsyncFeatureMapExecutorResults
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(
- asyncFeatureHydrationResults = previousPipelineResult.asyncFeatureHydrationResults match {
- case Some(existingResults) => Some(existingResults ++ executorResult)
- case None => Some(executorResult)
- })
-
- override def queryUpdater(
- query: Query,
- executorResult: AsyncFeatureMapExecutorResults
- ): Query =
- if (executorResult.featureMapsByStep
- .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) {
- query
- } else {
- query
- .withFeatureMap(
- query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep(
- stepToHydrateFor)).asInstanceOf[Query]
- }
- }
-
- def candidatePipelinesStep(
- candidatePipelines: Seq[CandidatePipeline[Query]],
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] =
- new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.candidatePipelinesStep
-
- override def executorArrow: Arrow[CandidatePipeline.Inputs[
- Query
- ], CandidatePipelineExecutorResult] =
- candidatePipelineExecutor
- .arrow(
- candidatePipelines,
- defaultFailOpenPolicy,
- failOpenPolicies,
- qualityFactorObserverByPipeline,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): CandidatePipeline.Inputs[
- Query
- ] = CandidatePipeline.Inputs(query, Seq.empty)
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: CandidatePipelineExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(candidatePipelineResults = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: CandidatePipelineExecutorResult
- ): Query = {
- val updatedFeatureMap = query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap
- query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]
- }
- }
-
- def dependentCandidatePipelinesStep(
- candidatePipelines: Seq[CandidatePipeline[Query]],
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] =
- new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.dependentCandidatePipelinesStep
-
- override def executorArrow: Arrow[CandidatePipeline.Inputs[
- Query
- ], CandidatePipelineExecutorResult] =
- candidatePipelineExecutor
- .arrow(
- candidatePipelines,
- defaultFailOpenPolicy,
- failOpenPolicies,
- qualityFactorObserverByPipeline,
- context
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): CandidatePipeline.Inputs[
- Query
- ] = {
- val previousCandidates = previousResult.candidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "Candidates")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
-
- CandidatePipeline.Inputs(query, previousCandidates)
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: CandidatePipelineExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(dependentCandidatePipelineResults = Some(executorResult))
-
- override def queryUpdater(
- query: Query,
- executorResult: CandidatePipelineExecutorResult
- ): Query = {
- val updatedFeatureMap = query.features
- .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap
- query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]
- }
- }
-
- abstract class FilterStep(
- filters: Seq[Filter[Query, Candidate]],
- context: Executor.Context,
- override val identifier: PipelineStepIdentifier)
- extends Step[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- FilterExecutorResult[Candidate]
- ] {
-
- def itemCandidates(
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Seq[CandidateWithDetails]
-
- override def executorArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- FilterExecutorResult[Candidate]
- ] =
- filterExecutor.arrow(filters, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): (Query, Seq[CandidateWithFeatures[Candidate]]) = {
-
- val extractedItemCandidates = itemCandidates(previousResult).collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
-
- (query, extractedItemCandidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]])
- }
- }
-
- def postCandidatePipelinesSelectorStep(
- selectors: Seq[Selector[Query]],
- context: Executor.Context
- ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.postCandidatePipelinesSelectorsStep
-
- override def executorArrow: Arrow[SelectorExecutor.Inputs[
- Query
- ], SelectorExecutorResult] =
- selectorExecutor.arrow(selectors, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): SelectorExecutor.Inputs[Query] = {
- val candidatePipelineResults = previousResult.candidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "CandidatePipelineResults")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
- val dependentCandidatePipelineResults = previousResult.dependentCandidatePipelineResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "DependentCandidatePipelineResults")
- }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty))
-
- SelectorExecutor.Inputs(
- query = query,
- candidatesWithDetails = candidatePipelineResults ++ dependentCandidatePipelineResults
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: SelectorExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(postCandidatePipelinesSelectorResults = Some(executorResult))
- }
-
- def postCandidatePipelinesFeatureHydrationStep(
- hydrators: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]],
- context: Executor.Context
- ): Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] = new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.postCandidatePipelinesFeatureHydrationStep
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] =
- candidateFeatureHydratorExecutor.arrow(hydrators, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = {
- val selectedCandidatesResult =
- previousResult.postCandidatePipelinesSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "PostCandidatePipelinesSelectorResults")
- }.selectedCandidates
-
- CandidateFeatureHydratorExecutor.Inputs(
- query,
- selectedCandidatesResult.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]])
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate]
- ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy(
- postCandidatePipelinesFeatureHydrationResults = Some(executorResult)
- )
- }
-
- def globalFiltersStep(
- filters: Seq[Filter[Query, Candidate]],
- context: Executor.Context
- ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] =
- new FilterStep(filters, context, RecommendationPipelineConfig.globalFiltersStep) {
- override def itemCandidates(
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Seq[CandidateWithDetails] = {
- val candidates = previousResult.postCandidatePipelinesSelectorResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "PostCandidatePipelineSelectorResults")
- }.selectedCandidates.collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
-
- val featureMaps = previousResult.postCandidatePipelinesFeatureHydrationResults
- .getOrElse {
- throw InvalidStepStateException(
- identifier,
- "PostCandidatePipelineFeatureHydrationResults")
- }.results.map(_.features)
- // If no hydrators were run, this list would be empty. Otherwise, order and cardinality is
- // always ensured to match.
- if (featureMaps.isEmpty) {
- candidates
- } else {
- candidates.zip(featureMaps).map {
- case (candidate, featureMap) =>
- candidate.copy(features = candidate.features ++ featureMap)
- }
- }
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: FilterExecutorResult[Candidate]
- ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy(
- globalFilterResults = Some(executorResult)
- )
- }
-
- def scoringPipelinesStep(
- scoringPipelines: Seq[ScoringPipeline[Query, Candidate]],
- context: Executor.Context,
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver]
- ): Step[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[
- Candidate
- ]] =
- new Step[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[
- Candidate
- ]] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.scoringPipelinesStep
-
- override def executorArrow: Arrow[
- ScoringPipelineExecutor.Inputs[Query],
- ScoringPipelineExecutorResult[Candidate]
- ] = scoringPipelineExecutor.arrow(
- scoringPipelines,
- context,
- defaultFailOpenPolicy,
- failOpenPolicies,
- qualityFactorObserverByPipeline
- )
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): ScoringPipelineExecutor.Inputs[Query] = {
- val selectedCandidates =
- previousResult.postCandidatePipelinesSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "PostCandidatePipelinesSelectorResults")
- }.selectedCandidates
-
- val itemCandidates = selectedCandidates.collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
-
- val featureMaps = previousResult.postCandidatePipelinesFeatureHydrationResults
- .getOrElse {
- throw InvalidStepStateException(
- identifier,
- "PostCandidatePipelineFeatureHydrationResults")
- }.results.map(_.features)
- // If no hydrators were run, this list would be empty. Otherwise, order and cardinality is
- // always ensured to match.
- val updatedCandidates = if (featureMaps.isEmpty) {
- itemCandidates
- } else {
- itemCandidates.zip(featureMaps).map {
- case (candidate, featureMap) =>
- candidate.copy(features = candidate.features ++ featureMap)
- }
- }
-
- // Filter the original list of candidates to keep only the ones that were kept from
- // filtering
- val filterResults: Set[Candidate] = previousResult.globalFilterResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "FilterResults")
- }.result.toSet
-
- val filteredItemCandidates = updatedCandidates.filter { itemCandidate =>
- filterResults.contains(itemCandidate.candidate.asInstanceOf[Candidate])
- }
-
- ScoringPipelineExecutor.Inputs(
- query,
- filteredItemCandidates
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: ScoringPipelineExecutorResult[Candidate]
- ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult
- .copy(scoringPipelineResults = Some(executorResult))
- }
-
- def resultSelectorsStep(
- selectors: Seq[Selector[Query]],
- context: Executor.Context
- ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.resultSelectorsStep
-
- override def executorArrow: Arrow[SelectorExecutor.Inputs[
- Query
- ], SelectorExecutorResult] =
- selectorExecutor.arrow(selectors, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): SelectorExecutor.Inputs[Query] = {
-
- /**
- * See [[ScoringPipelineExecutor]], scoringPipelineResults contains the fully re-merged
- * and updated FeatureMap so there's no need to do any recomposition. Scoring Pipeline Results
- * has only candidates that were kept in previous filtering, with their final merged feature
- * map.
- */
- val scorerResults = previousResult.scoringPipelineResults.getOrElse {
- throw InvalidStepStateException(identifier, "Scores")
- }
-
- SelectorExecutor.Inputs(
- query = query,
- candidatesWithDetails = scorerResults.result
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: SelectorExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(resultSelectorResults = Some(executorResult))
- }
-
- def postSelectionFiltersStep(
- filters: Seq[Filter[Query, Candidate]],
- context: Executor.Context
- ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] =
- new FilterStep(filters, context, RecommendationPipelineConfig.postSelectionFiltersStep) {
-
- override def itemCandidates(
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): Seq[CandidateWithDetails] = {
- previousResult.resultSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "Candidates")
- }.selectedCandidates
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: FilterExecutorResult[Candidate]
- ): RecommendationPipelineResult[Candidate, Result] = {
- previousPipelineResult.copy(postSelectionFilterResults = Some(executorResult))
- }
- }
-
- def decoratorStep(
- decorator: Option[CandidateDecorator[Query, Candidate]],
- context: Executor.Context
- ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] =
- new Step[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] {
- override def identifier: PipelineStepIdentifier = RecommendationPipelineConfig.decoratorStep
-
- override lazy val executorArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- CandidateDecoratorExecutorResult
- ] =
- candidateDecoratorExecutor.arrow(decorator, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): (Query, Seq[CandidateWithFeatures[Candidate]]) = {
-
- val selectorResults = previousResult.resultSelectorResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }.selectedCandidates
- .collect { case candidate: ItemCandidateWithDetails => candidate }
-
- val filterResults = previousResult.postSelectionFilterResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "PostSelectionFilterResults")
- }.result.toSet
-
- val itemCandidateWithDetailsPostFiltering =
- selectorResults
- .filter(candidateWithDetails =>
- filterResults.contains(
- candidateWithDetails.candidate
- .asInstanceOf[Candidate]))
- .asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]
-
- (query, itemCandidateWithDetailsPostFiltering)
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: CandidateDecoratorExecutorResult
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(
- candidateDecoratorResult = Some(executorResult)
- )
- }
-
- def domainMarshallingStep(
- domainMarshaller: DomainMarshaller[Query, DomainResultType],
- context: Executor.Context
- ): Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[
- DomainResultType
- ]] =
- new Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[
- DomainResultType
- ]] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.domainMarshallerStep
-
- override def executorArrow: Arrow[
- DomainMarshallerExecutor.Inputs[Query],
- DomainMarshallerExecutor.Result[DomainResultType]
- ] =
- domainMarshallerExecutor.arrow(domainMarshaller, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): DomainMarshallerExecutor.Inputs[Query] = {
- val selectorResults = previousResult.resultSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }
-
- val filterResults = previousResult.postSelectionFilterResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "PostSelectionFilterResults")
- }.result.toSet
-
- val filteredResults = selectorResults.selectedCandidates.collect {
- case candidate: ItemCandidateWithDetails
- if filterResults.contains(candidate.candidate.asInstanceOf[Candidate]) =>
- candidate
- }
-
- val decoratorResults = previousResult.candidateDecoratorResult
- .getOrElse(throw InvalidStepStateException(identifier, "DecoratorStep")).result.map {
- decoration =>
- decoration.candidate -> decoration.presentation
- }.toMap
-
- val finalResults = filteredResults.map { itemWithDetails =>
- decoratorResults.get(itemWithDetails.candidate) match {
- case Some(presentation: ItemPresentation) =>
- if (itemWithDetails.presentation.isDefined) {
- throw PipelineFailure(
- category = MisconfiguredDecorator,
- reason = "Item Candidate already decorated",
- componentStack = Some(context.componentStack))
- } else {
- itemWithDetails.copy(presentation = Some(presentation))
- }
- case Some(_) =>
- throw PipelineFailure(
- category = MisconfiguredDecorator,
- reason = "Item Candidate got back a non ItemPresentation from decorator",
- componentStack = Some(context.componentStack))
- case None => itemWithDetails
- }
- }
- DomainMarshallerExecutor.Inputs(
- query = query,
- candidatesWithDetails = finalResults
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: DomainMarshallerExecutor.Result[DomainResultType]
- ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy(
- domainMarshallerResults = Some(executorResult)
- )
- }
-
- def resultSideEffectsStep(
- sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]],
- context: Executor.Context
- ): Step[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] = new Step[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.resultSideEffectsStep
-
- override def executorArrow: Arrow[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] = pipelineResultSideEffectExecutor.arrow(sideEffects, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = {
-
- // Re-apply decorations to the selected results
- val resultSelectorResults = {
- val decoratorResults = previousResult.candidateDecoratorResult
- .getOrElse(throw InvalidStepStateException(identifier, "DecoratorStep")).result.map {
- decoration =>
- decoration.candidate -> decoration.presentation
- }.toMap
-
- val previousSelectorResults = previousResult.resultSelectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }
-
- val filterResults = previousResult.postSelectionFilterResults
- .getOrElse {
- throw InvalidStepStateException(identifier, "PostSelectionFilterResults")
- }.result.toSet
-
- val filteredSelectorResults = previousSelectorResults.selectedCandidates.collect {
- case candidate: ItemCandidateWithDetails
- if filterResults.contains(candidate.candidate.asInstanceOf[Candidate]) =>
- candidate
- }
-
- val decoratedSelectedResults = filteredSelectorResults.map {
- case itemWithDetails: ItemCandidateWithDetails =>
- decoratorResults.get(itemWithDetails.candidate) match {
- case Some(presentation: ItemPresentation) =>
- if (itemWithDetails.presentation.isDefined) {
- throw PipelineFailure(
- category = MisconfiguredDecorator,
- reason = "Item Candidate already decorated",
- componentStack = Some(context.componentStack))
- } else {
- itemWithDetails.copy(presentation = Some(presentation))
- }
- case Some(_) =>
- throw PipelineFailure(
- category = MisconfiguredDecorator,
- reason = "Item Candidate got back a non ItemPresentation from decorator",
- componentStack = Some(context.componentStack))
- case None => itemWithDetails
- }
- case item =>
- // This branch should be impossible to hit since we do a .collect on ItemCandidateWithDetails
- // as part of executing the candidate pipelines.
- throw PipelineFailure(
- category = IllegalStateFailure,
- reason =
- s"Only ItemCandidateWithDetails expected in pipeline, found: ${item.toString}",
- componentStack = Some(context.componentStack)
- )
- }
-
- previousSelectorResults.copy(selectedCandidates = decoratedSelectedResults)
- }
-
- val domainMarshallerResults = previousResult.domainMarshallerResults.getOrElse {
- throw InvalidStepStateException(identifier, "DomainMarshallerResults")
- }
-
- PipelineResultSideEffect.Inputs[Query, DomainResultType](
- query = query,
- selectedCandidates = resultSelectorResults.selectedCandidates,
- remainingCandidates = resultSelectorResults.remainingCandidates,
- droppedCandidates = resultSelectorResults.droppedCandidates,
- response = domainMarshallerResults.result.asInstanceOf[DomainResultType]
- )
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: PipelineResultSideEffectExecutor.Result
- ): RecommendationPipelineResult[Candidate, Result] =
- previousPipelineResult.copy(resultSideEffectResults = Some(executorResult))
- }
-
- def transportMarshallingStep(
- transportMarshaller: TransportMarshaller[DomainResultType, Result],
- context: Executor.Context
- ): Step[
- TransportMarshallerExecutor.Inputs[DomainResultType],
- TransportMarshallerExecutor.Result[Result]
- ] = new Step[TransportMarshallerExecutor.Inputs[
- DomainResultType
- ], TransportMarshallerExecutor.Result[Result]] {
- override def identifier: PipelineStepIdentifier =
- RecommendationPipelineConfig.transportMarshallerStep
-
- override def executorArrow: Arrow[TransportMarshallerExecutor.Inputs[
- DomainResultType
- ], TransportMarshallerExecutor.Result[Result]] =
- transportMarshallerExecutor.arrow(transportMarshaller, context)
-
- override def inputAdaptor(
- query: Query,
- previousResult: RecommendationPipelineResult[Candidate, Result]
- ): TransportMarshallerExecutor.Inputs[DomainResultType] = {
- val domainMarshallingResults = previousResult.domainMarshallerResults.getOrElse {
- throw InvalidStepStateException(identifier, "DomainMarshallerResults")
- }
-
- // Since the PipelineResult just uses HasMarshalling
- val domainResult = domainMarshallingResults.result.asInstanceOf[DomainResultType]
-
- TransportMarshallerExecutor.Inputs(domainResult)
- }
-
- override def resultUpdater(
- previousPipelineResult: RecommendationPipelineResult[Candidate, Result],
- executorResult: TransportMarshallerExecutor.Result[Result]
- ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy(
- transportMarshallerResults = Some(executorResult),
- result = Some(executorResult.result)
- )
- }
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- config: RecommendationPipelineConfig[
- Query,
- Candidate,
- DomainResultType,
- Result
- ]
- ): RecommendationPipeline[Query, Candidate, Result] = {
- val pipelineIdentifier = config.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val decorator = config.decorator.map(decorator =>
- CandidateDecorator.copyWithUpdatedIdentifier(decorator, pipelineIdentifier))
-
- val qualityFactorStatus: QualityFactorStatus =
- QualityFactorStatus.build(config.qualityFactorConfigs)
-
- val qualityFactorObserverByPipeline =
- qualityFactorStatus.qualityFactorByPipeline.mapValues { qualityFactor =>
- qualityFactor.buildObserver()
- }
-
- buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver)
-
- val candidatePipelines: Seq[CandidatePipeline[Query]] = config.candidatePipelines.map {
- pipelineConfig: CandidatePipelineConfig[Query, _, _, _] =>
- pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory)
- }
-
- val dependentCandidatePipelines: Seq[CandidatePipeline[Query]] =
- config.dependentCandidatePipelines.map {
- pipelineConfig: DependentCandidatePipelineConfig[Query, _, _, _] =>
- pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory)
- }
-
- val scoringPipelines: Seq[ScoringPipeline[Query, Candidate]] = config.scoringPipelines.map {
- pipelineConfig: ScoringPipelineConfig[Query, Candidate] =>
- pipelineConfig.build(context.componentStack, scoringPipelineBuilderFactory)
- }
-
- val builtSteps = Seq(
- qualityFactorStep(qualityFactorStatus),
- gatesStep(config.gates, context),
- fetchQueryFeaturesStep(
- config.fetchQueryFeatures,
- RecommendationPipelineConfig.fetchQueryFeaturesStep,
- (previousPipelineResult, executorResult) =>
- previousPipelineResult.copy(queryFeatures = Some(executorResult)),
- context
- ),
- fetchQueryFeaturesStep(
- config.fetchQueryFeaturesPhase2,
- RecommendationPipelineConfig.fetchQueryFeaturesPhase2Step,
- (previousPipelineResult, executorResult) =>
- previousPipelineResult.copy(
- queryFeaturesPhase2 = Some(executorResult),
- mergedAsyncQueryFeatures = Some(
- previousPipelineResult.queryFeatures
- .getOrElse(throw InvalidStepStateException(
- RecommendationPipelineConfig.fetchQueryFeaturesPhase2Step,
- "QueryFeatures"))
- .asyncFeatureMap ++ executorResult.asyncFeatureMap)
- ),
- context
- ),
- asyncFeaturesStep(RecommendationPipelineConfig.candidatePipelinesStep, context),
- candidatePipelinesStep(
- candidatePipelines,
- config.defaultFailOpenPolicy,
- config.candidatePipelineFailOpenPolicies,
- qualityFactorObserverByPipeline,
- context),
- asyncFeaturesStep(RecommendationPipelineConfig.dependentCandidatePipelinesStep, context),
- dependentCandidatePipelinesStep(
- dependentCandidatePipelines,
- config.defaultFailOpenPolicy,
- config.candidatePipelineFailOpenPolicies,
- qualityFactorObserverByPipeline,
- context),
- asyncFeaturesStep(RecommendationPipelineConfig.postCandidatePipelinesSelectorsStep, context),
- postCandidatePipelinesSelectorStep(config.postCandidatePipelinesSelectors, context),
- asyncFeaturesStep(
- RecommendationPipelineConfig.postCandidatePipelinesFeatureHydrationStep,
- context),
- postCandidatePipelinesFeatureHydrationStep(
- config.postCandidatePipelinesFeatureHydration,
- context),
- asyncFeaturesStep(RecommendationPipelineConfig.globalFiltersStep, context),
- globalFiltersStep(config.globalFilters, context),
- asyncFeaturesStep(RecommendationPipelineConfig.scoringPipelinesStep, context),
- scoringPipelinesStep(
- scoringPipelines,
- context,
- config.defaultFailOpenPolicy,
- config.scoringPipelineFailOpenPolicies,
- qualityFactorObserverByPipeline
- ),
- asyncFeaturesStep(RecommendationPipelineConfig.resultSelectorsStep, context),
- resultSelectorsStep(config.resultSelectors, context),
- asyncFeaturesStep(RecommendationPipelineConfig.postSelectionFiltersStep, context),
- postSelectionFiltersStep(config.postSelectionFilters, context),
- asyncFeaturesStep(RecommendationPipelineConfig.decoratorStep, context),
- decoratorStep(decorator, context),
- domainMarshallingStep(config.domainMarshaller, context),
- asyncFeaturesStep(RecommendationPipelineConfig.resultSideEffectsStep, context),
- resultSideEffectsStep(config.resultSideEffects, context),
- transportMarshallingStep(config.transportMarshaller, context)
- )
-
- val finalArrow = buildCombinedArrowFromSteps(
- steps = builtSteps,
- context = context,
- initialEmptyResult = RecommendationPipelineResult.empty,
- stepsInOrderFromConfig = RecommendationPipelineConfig.stepsInOrder
- )
-
- val configFromBuilder = config
- new RecommendationPipeline[Query, Candidate, Result] {
- override private[core] val config: RecommendationPipelineConfig[
- Query,
- Candidate,
- _,
- Result
- ] =
- configFromBuilder
- override val arrow: Arrow[Query, RecommendationPipelineResult[Candidate, Result]] =
- finalArrow
- override val identifier: RecommendationPipelineIdentifier = pipelineIdentifier
- override val alerts: Seq[Alert] = config.alerts
- override val children: Seq[Component] =
- config.gates ++
- config.fetchQueryFeatures ++
- candidatePipelines ++
- dependentCandidatePipelines ++
- config.postCandidatePipelinesFeatureHydration ++
- config.globalFilters ++
- scoringPipelines ++
- config.postSelectionFilters ++
- config.resultSideEffects ++
- decorator.toSeq ++
- Seq(config.domainMarshaller, config.transportMarshaller)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala
deleted file mode 100644
index 6df35985a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.recommendation
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineBuilderFactory
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class RecommendationPipelineBuilderFactory @Inject() (
- candidatePipelineExecutor: CandidatePipelineExecutor,
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor,
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- filterExecutor: FilterExecutor,
- scoringPipelineExecutor: ScoringPipelineExecutor,
- candidateDecoratorExecutor: CandidateDecoratorExecutor,
- domainMarshallerExecutor: DomainMarshallerExecutor,
- transportMarshallerExecutor: TransportMarshallerExecutor,
- pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory,
- scoringPipelineBuilderFactory: ScoringPipelineBuilderFactory,
- statsReceiver: StatsReceiver) {
-
- def get[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- DomainResultType <: HasMarshalling,
- Result
- ]: RecommendationPipelineBuilder[Query, Candidate, DomainResultType, Result] = {
- new RecommendationPipelineBuilder[Query, Candidate, DomainResultType, Result](
- candidatePipelineExecutor,
- gateExecutor,
- selectorExecutor,
- queryFeatureHydratorExecutor,
- asyncFeatureMapExecutor,
- candidateFeatureHydratorExecutor,
- filterExecutor,
- scoringPipelineExecutor,
- candidateDecoratorExecutor,
- domainMarshallerExecutor,
- transportMarshallerExecutor,
- pipelineResultSideEffectExecutor,
- candidatePipelineBuilderFactory,
- scoringPipelineBuilderFactory,
- statsReceiver
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala
deleted file mode 100644
index 1e2fa59c2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala
+++ /dev/null
@@ -1,262 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.recommendation
-
-import com.twitter.product_mixer.component_library.selector.InsertAppendResults
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.functional_component.gate.Gate
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.PipelineConfig
-import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineConfig
-import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig
-
-/**
- * This is the configuration necessary to generate a Recommendation Pipeline. Product code should create a
- * RecommendationPipelineConfig, and then use a RecommendationPipelineBuilder to get the final RecommendationPipeline which can
- * process requests.
- *
- * @tparam Query - The domain model for the query or request
- * @tparam Candidate - The type of the candidates that the Candidate Pipelines are generating
- * @tparam UnmarshalledResultType - The result type of the pipeline, but before marshalling to a wire protocol like URT
- * @tparam Result - The final result that will be served to users
- */
-trait RecommendationPipelineConfig[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- UnmarshalledResultType <: HasMarshalling,
- Result]
- extends PipelineConfig {
-
- override val identifier: RecommendationPipelineIdentifier
-
- /**
- * Recommendation Pipeline Gates will be executed before any other step (including retrieval from candidate
- * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution.
- */
- def gates: Seq[Gate[Query]] = Seq.empty
-
- /**
- * A recommendation pipeline can fetch query-level features before candidate pipelines are executed.
- */
- def fetchQueryFeatures: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty
-
- /**
- * Candidate pipelines retrieve candidates for possible inclusion in the result
- */
- def fetchQueryFeaturesPhase2: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty
-
- /**
- * What candidate pipelines should this Recommendations Pipeline get candidate from?
- */
- def candidatePipelines: Seq[CandidatePipelineConfig[Query, _, _, _]]
-
- /**
- * Dependent candidate pipelines to retrieve candidates that depend on the result of [[candidatePipelines]]
- * [[DependentCandidatePipelineConfig]] have access to the list of previously retrieved & decorated
- * candidates for use in constructing the query object.
- */
- def dependentCandidatePipelines: Seq[DependentCandidatePipelineConfig[Query, _, _, _]] = Seq.empty
-
- /**
- * Takes final ranked list of candidates & apply any business logic (e.g, deduplicating and merging
- * candidates before scoring).
- */
- def postCandidatePipelinesSelectors: Seq[Selector[Query]] = Seq(InsertAppendResults(AllPipelines))
-
- /**
- * After selectors are run, you can fetch features for each candidate.
- * The existing features from previous hydrations are passed in as inputs. You are not expected to
- * put them into the resulting feature map yourself - they will be merged for you by the platform.
- */
- def postCandidatePipelinesFeatureHydration: Seq[
- BaseCandidateFeatureHydrator[Query, Candidate, _]
- ] =
- Seq.empty
-
- /**
- * Global filters to run on all candidates.
- */
- def globalFilters: Seq[Filter[Query, Candidate]] = Seq.empty
-
- /**
- * By default, a Recommendation Pipeline will fail closed - if any candidate or scoring
- * pipeline fails to return a result, then the Recommendation Pipeline will not return a result.
- * You can adjust this default policy, or provide specific policies to specific pipelines.
- * Those specific policies will take priority.
- *
- * FailOpenPolicy.All will always fail open (the RecommendationPipeline will continue without that pipeline)
- * FailOpenPolicy.Never will always fail closed (the RecommendationPipeline will fail if that pipeline fails)
- *
- * There's a default policy, and a specific Map of policies that takes precedence.
- */
- def defaultFailOpenPolicy: FailOpenPolicy = FailOpenPolicy(Set(ClosedGate))
- def candidatePipelineFailOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy] =
- Map.empty
- def scoringPipelineFailOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy] = Map.empty
-
- /**
- ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific candidate pipelines
- * using [[ComponentIdentifier]].
- */
- def qualityFactorConfigs: Map[ComponentIdentifier, QualityFactorConfig] =
- Map.empty
-
- /**
- * Scoring pipelines for scoring candidates.
- * @note These do not drop or re-order candidates, you should do those in the sub-sequent selectors
- * step based off of the scores on candidates set in those [[ScoringPipeline]]s.
- */
- def scoringPipelines: Seq[ScoringPipelineConfig[Query, Candidate]]
-
- /**
- * Takes final ranked list of candidates & apply any business logic (e.g, capping number
- * of ad accounts or pacing ad accounts).
- */
- def resultSelectors: Seq[Selector[Query]]
-
- /**
- * Takes the final selected list of candidates and applies a final list of filters.
- * Useful for doing very expensive filtering at the end of your pipeline.
- */
- def postSelectionFilters: Seq[Filter[Query, Candidate]] = Seq.empty
-
- /**
- * Decorators allow for adding Presentations to candidates. While the Presentation can contain any
- * arbitrary data, Decorators are often used to add a UrtItemPresentation for URT item support. Most
- * customers will prefer to set a decorator in their respective candidate pipeline, however, a final
- * global one is available for those that do global decoration as late possible to avoid unnecessary hydrations.
- * @note This decorator can only return an ItemPresentation.
- * @note This decorator cannot decorate an already decorated candidate from the prior decorator
- * step in candidate pipelines.
- */
- def decorator: Option[CandidateDecorator[Query, Candidate]] = None
-
- /**
- * Domain marshaller transforms the selections into the model expected by the marshaller
- */
- def domainMarshaller: DomainMarshaller[Query, UnmarshalledResultType]
-
- /**
- * Mixer result side effects that are executed after selection and domain marshalling
- */
- def resultSideEffects: Seq[PipelineResultSideEffect[Query, UnmarshalledResultType]] = Seq()
-
- /**
- * Transport marshaller transforms the model into our line-level API like URT or JSON
- */
- def transportMarshaller: TransportMarshaller[UnmarshalledResultType, Result]
-
- /**
- * A pipeline can define a partial function to rescue failures here. They will be treated as failures
- * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here).
- */
- def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty
-
- /**
- * Alerts can be used to indicate the pipeline's service level objectives. Alerts and
- * dashboards will be automatically created based on this information.
- */
- val alerts: Seq[Alert] = Seq.empty
-
- /**
- * This method is used by the product mixer framework to build the pipeline.
- */
- private[core] final def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- builder: RecommendationPipelineBuilderFactory
- ): RecommendationPipeline[Query, Candidate, Result] =
- builder.get.build(parentComponentIdentifierStack, this)
-}
-
-object RecommendationPipelineConfig extends PipelineConfigCompanion {
- val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor")
- val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates")
- val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures")
- val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier = PipelineStepIdentifier(
- "FetchQueryFeaturesPhase2")
- val candidatePipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidatePipelines")
- val dependentCandidatePipelinesStep: PipelineStepIdentifier =
- PipelineStepIdentifier("DependentCandidatePipelines")
- val postCandidatePipelinesSelectorsStep: PipelineStepIdentifier =
- PipelineStepIdentifier("PostCandidatePipelinesSelectors")
- val postCandidatePipelinesFeatureHydrationStep: PipelineStepIdentifier =
- PipelineStepIdentifier("PostCandidatePipelinesFeatureHydration")
- val globalFiltersStep: PipelineStepIdentifier = PipelineStepIdentifier("GlobalFilters")
- val scoringPipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("ScoringPipelines")
- val resultSelectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSelectors")
- val postSelectionFiltersStep: PipelineStepIdentifier = PipelineStepIdentifier(
- "PostSelectionFilters")
- val decoratorStep: PipelineStepIdentifier = PipelineStepIdentifier("Decorator")
- val domainMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier("DomainMarshaller")
- val resultSideEffectsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSideEffects")
- val transportMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier(
- "TransportMarshaller")
-
- /** All the Steps which are executed by a [[RecommendationPipeline]] in the order in which they are run */
- override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq(
- qualityFactorStep,
- gatesStep,
- fetchQueryFeaturesStep,
- fetchQueryFeaturesPhase2Step,
- asyncFeaturesStep(candidatePipelinesStep),
- candidatePipelinesStep,
- asyncFeaturesStep(dependentCandidatePipelinesStep),
- dependentCandidatePipelinesStep,
- asyncFeaturesStep(postCandidatePipelinesSelectorsStep),
- postCandidatePipelinesSelectorsStep,
- asyncFeaturesStep(postCandidatePipelinesFeatureHydrationStep),
- postCandidatePipelinesFeatureHydrationStep,
- asyncFeaturesStep(globalFiltersStep),
- globalFiltersStep,
- asyncFeaturesStep(scoringPipelinesStep),
- scoringPipelinesStep,
- asyncFeaturesStep(resultSelectorsStep),
- resultSelectorsStep,
- asyncFeaturesStep(postSelectionFiltersStep),
- postSelectionFiltersStep,
- asyncFeaturesStep(decoratorStep),
- decoratorStep,
- domainMarshallerStep,
- asyncFeaturesStep(resultSideEffectsStep),
- resultSideEffectsStep,
- transportMarshallerStep
- )
-
- /**
- * All the Steps which an [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator AsyncHydrator]]
- * can be configured to [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator.hydrateBefore hydrateBefore]]
- */
- override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set(
- candidatePipelinesStep,
- dependentCandidatePipelinesStep,
- postCandidatePipelinesSelectorsStep,
- postCandidatePipelinesFeatureHydrationStep,
- globalFiltersStep,
- scoringPipelinesStep,
- resultSelectorsStep,
- postSelectionFiltersStep,
- decoratorStep,
- resultSideEffectsStep,
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala
deleted file mode 100644
index 9e75c8db3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.recommendation
-
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutorResult
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-
-case class RecommendationPipelineResult[Candidate <: UniversalNoun[Any], ResultType](
- qualityFactorResult: Option[QualityFactorExecutorResult],
- gateResult: Option[GateExecutorResult],
- queryFeatures: Option[QueryFeatureHydratorExecutor.Result],
- queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result],
- mergedAsyncQueryFeatures: Option[AsyncFeatureMap],
- candidatePipelineResults: Option[CandidatePipelineExecutorResult],
- dependentCandidatePipelineResults: Option[CandidatePipelineExecutorResult],
- postCandidatePipelinesSelectorResults: Option[SelectorExecutorResult],
- postCandidatePipelinesFeatureHydrationResults: Option[
- CandidateFeatureHydratorExecutorResult[Candidate]
- ],
- globalFilterResults: Option[FilterExecutorResult[Candidate]],
- scoringPipelineResults: Option[ScoringPipelineExecutorResult[Candidate]],
- resultSelectorResults: Option[SelectorExecutorResult],
- postSelectionFilterResults: Option[FilterExecutorResult[Candidate]],
- candidateDecoratorResult: Option[CandidateDecoratorExecutorResult],
- domainMarshallerResults: Option[DomainMarshallerExecutor.Result[HasMarshalling]],
- resultSideEffectResults: Option[PipelineResultSideEffectExecutor.Result],
- asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults],
- transportMarshallerResults: Option[TransportMarshallerExecutor.Result[ResultType]],
- failure: Option[PipelineFailure],
- result: Option[ResultType])
- extends PipelineResult[ResultType] {
- override val resultSize: Int = result match {
- case Some(seqResult @ Seq(_)) => seqResult.length
- case Some(_) => 1
- case None => 0
- }
-
- override def withFailure(
- failure: PipelineFailure
- ): RecommendationPipelineResult[Candidate, ResultType] =
- copy(failure = Some(failure))
- override def withResult(result: ResultType): RecommendationPipelineResult[Candidate, ResultType] =
- copy(result = Some(result))
-}
-
-object RecommendationPipelineResult {
- def empty[A <: UniversalNoun[Any], B]: RecommendationPipelineResult[A, B] =
- RecommendationPipelineResult(
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD
deleted file mode 100644
index 43c431a64..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector:insert_append_results",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala
deleted file mode 100644
index 9b3bf2a26..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala
+++ /dev/null
@@ -1,202 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult
-import com.twitter.product_mixer.core.gate.ParamGate
-import com.twitter.product_mixer.core.gate.ParamGate._
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.NewPipelineBuilder
-import com.twitter.product_mixer.core.pipeline.NewPipelineArrowBuilder
-import com.twitter.product_mixer.core.pipeline.NewPipelineResult
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.state.HasResult
-import com.twitter.product_mixer.core.pipeline.step.candidate_feature_hydrator.CandidateFeatureHydratorStep
-import com.twitter.product_mixer.core.pipeline.step.gate.GateStep
-import com.twitter.product_mixer.core.pipeline.step.scorer.ScorerStep
-import com.twitter.product_mixer.core.pipeline.step.selector.SelectorStep
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-import scala.collection.immutable.ListMap
-
-/**
- * NewScoringPipelineBuilder builds [[ScoringPipeline]]s from [[ScoringPipelineConfig]]s.
- * New because it's meant to eventually replace [[ScoringPipelineBuilder]]
- * You should inject a [[ScoringPipelineBuilderFactory]] and call `.get` to build these.
- *
- * @see [[ScoringPipelineConfig]] for the description of the type parameters
- * @tparam Query the type of query these accept.
- * @tparam Candidate the domain model for the candidate being scored
- */
-class NewScoringPipelineBuilder[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] @Inject() (
- selectionStep: SelectorStep[Query, ScoringPipelineState[Query, Candidate]],
- gateStep: GateStep[Query, ScoringPipelineState[Query, Candidate]],
- candidateFeatureHydrationStep: CandidateFeatureHydratorStep[
- Query,
- Candidate,
- ScoringPipelineState[Query, Candidate]
- ],
- scorerStep: ScorerStep[Query, Candidate, ScoringPipelineState[Query, Candidate]])
- extends NewPipelineBuilder[ScoringPipelineConfig[Query, Candidate], Seq[
- CandidateWithFeatures[Candidate]
- ], ScoringPipelineState[Query, Candidate], ScoringPipeline[Query, Candidate]] {
-
- override def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- arrowBuilder: NewPipelineArrowBuilder[ArrowResult, ArrowState],
- scoringPipelineConfig: ScoringPipelineConfig[Query, Candidate]
- ): ScoringPipeline[Query, Candidate] = {
- val pipelineIdentifier = scoringPipelineConfig.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- scoringPipelineConfig.failureClassifier.orElse(
- StoppedGateException.classifier(ClosedGate))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val enabledGateOpt = scoringPipelineConfig.enabledDeciderParam.map { deciderParam =>
- ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam)
- }
- val supportedClientGateOpt = scoringPipelineConfig.supportedClientParam.map { param =>
- ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param)
- }
-
- /**
- * Evaluate enabled decider gate first since if it's off, there is no reason to proceed
- * Next evaluate supported client feature switch gate, followed by customer configured gates
- */
- val allGates =
- enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ scoringPipelineConfig.gates
-
- val underlyingArrow = arrowBuilder
- .add(ScoringPipelineConfig.gatesStep, gateStep, allGates)
- .add(ScoringPipelineConfig.selectorsStep, selectionStep, scoringPipelineConfig.selectors)
- .add(
- ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step,
- candidateFeatureHydrationStep,
- scoringPipelineConfig.preScoringFeatureHydrationPhase1)
- .add(
- ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step,
- candidateFeatureHydrationStep,
- scoringPipelineConfig.preScoringFeatureHydrationPhase2)
- .add(ScoringPipelineConfig.scorersStep, scorerStep, scoringPipelineConfig.scorers).buildArrow(
- context)
-
- val finalArrow = Arrow
- .map { inputs: ScoringPipeline.Inputs[Query] =>
- ScoringPipelineState[Query, Candidate](inputs.query, inputs.candidates, ListMap.empty)
- }.andThen(underlyingArrow).map { pipelineResult =>
- ScoringPipelineResult(
- gateResults = pipelineResult.executorResultsByPipelineStep
- .get(ScoringPipelineConfig.gatesStep)
- .map(_.asInstanceOf[GateExecutorResult]),
- selectorResults = pipelineResult.executorResultsByPipelineStep
- .get(ScoringPipelineConfig.selectorsStep)
- .map(_.asInstanceOf[SelectorExecutorResult]),
- preScoringHydrationPhase1Result = pipelineResult.executorResultsByPipelineStep
- .get(ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step)
- .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]),
- preScoringHydrationPhase2Result = pipelineResult.executorResultsByPipelineStep
- .get(ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step)
- .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]),
- scorerResults = pipelineResult.executorResultsByPipelineStep
- .get(ScoringPipelineConfig.scorersStep)
- .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]),
- failure = pipelineResult match {
- case failure: NewPipelineResult.Failure =>
- Some(failure.failure)
- case _ => None
- },
- result = pipelineResult match {
- case result: NewPipelineResult.Success[Seq[CandidateWithFeatures[Candidate]]] =>
- Some(result.result.map { candidateWithFeatures =>
- ScoredCandidateResult(
- candidateWithFeatures.candidate,
- candidateWithFeatures.features)
- })
- case _ => None
- }
- )
- }
-
- new ScoringPipeline[Query, Candidate] {
- override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] =
- finalArrow
-
- override val identifier: ScoringPipelineIdentifier = scoringPipelineConfig.identifier
-
- override val alerts: Seq[Alert] = scoringPipelineConfig.alerts
-
- override val children: Seq[Component] =
- allGates ++ scoringPipelineConfig.preScoringFeatureHydrationPhase1 ++ scoringPipelineConfig.preScoringFeatureHydrationPhase2 ++ scoringPipelineConfig.scorers
-
- override private[core] val config = scoringPipelineConfig
- }
- }
-}
-
-case class ScoringPipelineState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- override val query: Query,
- candidates: Seq[ItemCandidateWithDetails],
- override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult])
- extends HasQuery[Query, ScoringPipelineState[Query, Candidate]]
- with HasCandidatesWithDetails[ScoringPipelineState[Query, Candidate]]
- with HasCandidatesWithFeatures[Candidate, ScoringPipelineState[Query, Candidate]]
- with HasExecutorResults[ScoringPipelineState[Query, Candidate]]
- with HasResult[Seq[CandidateWithFeatures[Candidate]]] {
-
- override val candidatesWithDetails: Seq[CandidateWithDetails] = candidates
-
- override val candidatesWithFeatures: Seq[CandidateWithFeatures[Candidate]] =
- candidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]
-
- override val buildResult: Seq[CandidateWithFeatures[Candidate]] = candidatesWithFeatures
-
- override def updateCandidatesWithDetails(
- newCandidates: Seq[CandidateWithDetails]
- ): ScoringPipelineState[Query, Candidate] = {
- this.copy(candidates = newCandidates.asInstanceOf[Seq[ItemCandidateWithDetails]])
- }
-
- override def updateQuery(newQuery: Query): ScoringPipelineState[Query, Candidate] =
- this.copy(query = newQuery)
-
- override def updateDecorations(
- decoration: Seq[Decoration]
- ): ScoringPipelineState[Query, Candidate] = ???
-
- override def updateCandidatesWithFeatures(
- newCandidates: Seq[CandidateWithFeatures[Candidate]]
- ): ScoringPipelineState[Query, Candidate] = {
- val updatedCandidates = candidates.zip(newCandidates).map {
- case (itemCandidateWithDetails, newCandidate) =>
- itemCandidateWithDetails.copy(features =
- itemCandidateWithDetails.features ++ newCandidate.features)
- }
- this.copy(query, updatedCandidates)
- }
-
- override private[pipeline] def setExecutorResults(
- newMap: ListMap[PipelineStepIdentifier, ExecutorResult]
- ) = this.copy(executorResultsByPipelineStep = newMap)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala
deleted file mode 100644
index a02bbb8b4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.stitch.Arrow
-
-/**
- * A Scoring Pipeline
- *
- * This is an abstract class, as we only construct these via the [[ScoringPipelineBuilder]].
- *
- * A [[ScoringPipeline]] is capable of pre-filtering candidates for scoring, performing the scoring
- * then running selection heuristics (ranking, dropping, etc) based off of the score.
- * @tparam Query the domain model for the query or request
- * @tparam Candidate the domain model for the candidate being scored
- */
-abstract class ScoringPipeline[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends Pipeline[ScoringPipeline.Inputs[Query], Seq[ScoredCandidateResult[Candidate]]] {
- override private[core] val config: ScoringPipelineConfig[Query, Candidate]
- override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]]
- override val identifier: ScoringPipelineIdentifier
-}
-
-object ScoringPipeline {
- case class Inputs[+Query <: PipelineQuery](
- query: Query,
- candidates: Seq[ItemCandidateWithDetails])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala
deleted file mode 100644
index d597fa9a5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala
+++ /dev/null
@@ -1,367 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult
-import com.twitter.product_mixer.core.gate.ParamGate
-import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix
-import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.InvalidStepStateException
-import com.twitter.product_mixer.core.pipeline.PipelineBuilder
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline.Inputs
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * ScoringPipelineBuilder builds [[ScoringPipeline]]s from [[ScoringPipelineConfig]]s.
- *
- * You should inject a [[ScoringPipelineBuilderFactory]] and call `.get` to build these.
- *
- * @see [[ScoringPipelineConfig]] for the description of the type parameters
- * @tparam Query the type of query these accept.
- * @tparam Candidate the domain model for the candidate being scored
- */
-class ScoringPipelineBuilder[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] @Inject() (
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- override val statsReceiver: StatsReceiver)
- extends PipelineBuilder[Inputs[Query]] {
-
- override type UnderlyingResultType = Seq[ScoredCandidateResult[Candidate]]
- override type PipelineResultType = ScoringPipelineResult[Candidate]
-
- def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- config: ScoringPipelineConfig[Query, Candidate]
- ): ScoringPipeline[Query, Candidate] = {
-
- val pipelineIdentifier = config.identifier
-
- val context = Executor.Context(
- PipelineFailureClassifier(
- config.failureClassifier.orElse(StoppedGateException.classifier(ClosedGate))),
- parentComponentIdentifierStack.push(pipelineIdentifier)
- )
-
- val enabledGateOpt = config.enabledDeciderParam.map { deciderParam =>
- ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam)
- }
- val supportedClientGateOpt = config.supportedClientParam.map { param =>
- ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param)
- }
-
- /**
- * Evaluate enabled decider gate first since if it's off, there is no reason to proceed
- * Next evaluate supported client feature switch gate, followed by customer configured gates
- */
- val allGates = enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ config.gates
-
- val GatesStep = new Step[Query, GateExecutorResult] {
- override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.gatesStep
-
- override lazy val executorArrow: Arrow[Query, GateExecutorResult] =
- gateExecutor.arrow(allGates, context)
-
- override def inputAdaptor(
- query: ScoringPipeline.Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): Query = {
- query.query
- }
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: GateExecutorResult
- ): ScoringPipelineResult[Candidate] =
- previousPipelineResult.copy(gateResults = Some(executorResult))
- }
-
- val SelectorsStep = new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] {
- override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.selectorsStep
-
- override def executorArrow: Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- selectorExecutor.arrow(config.selectors, context)
-
- override def inputAdaptor(
- query: ScoringPipeline.Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): SelectorExecutor.Inputs[Query] = SelectorExecutor.Inputs(query.query, query.candidates)
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: SelectorExecutorResult
- ): ScoringPipelineResult[Candidate] =
- previousPipelineResult.copy(selectorResults = Some(executorResult))
- }
-
- val PreScoringFeatureHydrationPhase1Step =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] {
- override def identifier: PipelineStepIdentifier =
- ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.preScoringFeatureHydrationPhase1, context)
-
- override def inputAdaptor(
- query: ScoringPipeline.Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = {
- val selectedCandidatesResult = previousResult.selectorResults.getOrElse {
- throw InvalidStepStateException(identifier, "SelectorResults")
- }.selectedCandidates
-
- CandidateFeatureHydratorExecutor.Inputs(
- query.query,
- selectedCandidatesResult.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]])
- }
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate]
- ): ScoringPipelineResult[Candidate] = previousPipelineResult.copy(
- preScoringHydrationPhase1Result = Some(executorResult)
- )
- }
-
- val PreScoringFeatureHydrationPhase2Step =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] {
- override def identifier: PipelineStepIdentifier =
- ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step
-
- override def executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] =
- candidateFeatureHydratorExecutor.arrow(config.preScoringFeatureHydrationPhase2, context)
-
- override def inputAdaptor(
- query: ScoringPipeline.Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = {
- val preScoringHydrationPhase1FeatureMaps: Seq[FeatureMap] =
- previousResult.preScoringHydrationPhase1Result
- .getOrElse(
- throw InvalidStepStateException(identifier, "PreScoringHydrationPhase1Result"))
- .results.map(_.features)
-
- val itemCandidates = previousResult.selectorResults
- .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults"))
- .selectedCandidates.collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
- // If there is no feature hydration (empty results), no need to attempt merging.
- val candidates = if (preScoringHydrationPhase1FeatureMaps.isEmpty) {
- itemCandidates
- } else {
- itemCandidates.zip(preScoringHydrationPhase1FeatureMaps).map {
- case (itemCandidate, featureMap) =>
- itemCandidate.copy(features = itemCandidate.features ++ featureMap)
- }
- }
-
- CandidateFeatureHydratorExecutor.Inputs(
- query.query,
- candidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]])
- }
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate]
- ): ScoringPipelineResult[Candidate] = previousPipelineResult.copy(
- preScoringHydrationPhase2Result = Some(executorResult)
- )
- }
-
- def getMergedPreScoringFeatureMap(
- stepIdentifier: PipelineStepIdentifier,
- previousResult: ScoringPipelineResult[Candidate]
- ): Seq[FeatureMap] = {
- val preScoringHydrationPhase1FeatureMaps: Seq[FeatureMap] =
- previousResult.preScoringHydrationPhase1Result
- .getOrElse(
- throw InvalidStepStateException(
- stepIdentifier,
- "PreScoringHydrationPhase1Result")).results.map(_.features)
-
- val preScoringHydrationPhase2FeatureMaps: Seq[FeatureMap] =
- previousResult.preScoringHydrationPhase2Result
- .getOrElse(
- throw InvalidStepStateException(
- stepIdentifier,
- "PreScoringHydrationPhase2Result")).results.map(_.features)
- /*
- * If either pre-scoring hydration phase feature map is empty, no need to merge them,
- * we can just take all non-empty ones.
- */
- if (preScoringHydrationPhase1FeatureMaps.isEmpty) {
- preScoringHydrationPhase2FeatureMaps
- } else if (preScoringHydrationPhase2FeatureMaps.isEmpty) {
- preScoringHydrationPhase1FeatureMaps
- } else {
- // No need to check the size in both, since the inputs to both hydration phases are the
- // same and each phase ensures the number of candidates and ordering matches the input.
- preScoringHydrationPhase1FeatureMaps.zip(preScoringHydrationPhase2FeatureMaps).map {
- case (preScoringHydrationPhase1FeatureMap, preScoringHydrationPhasesFeatureMap) =>
- preScoringHydrationPhase1FeatureMap ++ preScoringHydrationPhasesFeatureMap
- }
- }
- }
-
- val ScorersStep =
- new Step[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] {
- override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.scorersStep
-
- override def inputAdaptor(
- query: ScoringPipeline.Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = {
-
- val mergedPreScoringFeatureHydrationFeatures: Seq[FeatureMap] =
- getMergedPreScoringFeatureMap(ScoringPipelineConfig.scorersStep, previousResult)
-
- val itemCandidates = previousResult.selectorResults
- .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults"))
- .selectedCandidates.collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
-
- // If there was no pre-scoring features hydration, no need to re-merge feature maps
- // and construct a new item candidate
- val updatedCandidates = if (mergedPreScoringFeatureHydrationFeatures.isEmpty) {
- itemCandidates
- } else {
- itemCandidates.zip(mergedPreScoringFeatureHydrationFeatures).map {
- case (itemCandidate, preScoringFeatureMap) =>
- itemCandidate.copy(features = itemCandidate.features ++ preScoringFeatureMap)
- }
- }
- CandidateFeatureHydratorExecutor.Inputs(
- query.query,
- updatedCandidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]])
- }
-
- override lazy val executorArrow: Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[
- Candidate
- ]
- ] = candidateFeatureHydratorExecutor.arrow(config.scorers.toSeq, context)
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate]
- ): ScoringPipelineResult[Candidate] =
- previousPipelineResult.copy(scorerResults = Some(executorResult))
- }
-
- val ResultStep =
- new Step[Seq[CandidateWithFeatures[UniversalNoun[Any]]], Seq[
- CandidateWithFeatures[UniversalNoun[Any]]
- ]] {
- override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.resultStep
-
- override def executorArrow: Arrow[Seq[CandidateWithFeatures[UniversalNoun[Any]]], Seq[
- CandidateWithFeatures[UniversalNoun[Any]]
- ]] = Arrow.identity
-
- override def inputAdaptor(
- query: Inputs[Query],
- previousResult: ScoringPipelineResult[Candidate]
- ): Seq[CandidateWithFeatures[UniversalNoun[Any]]] = previousResult.selectorResults
- .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults"))
- .selectedCandidates.collect {
- case itemCandidate: ItemCandidateWithDetails => itemCandidate
- }
-
- override def resultUpdater(
- previousPipelineResult: ScoringPipelineResult[Candidate],
- executorResult: Seq[CandidateWithFeatures[UniversalNoun[Any]]]
- ): ScoringPipelineResult[Candidate] = {
- val scorerResults: Seq[FeatureMap] = previousPipelineResult.scorerResults
- .getOrElse(throw InvalidStepStateException(identifier, "ScorerResult")).results.map(
- _.features)
-
- val mergedPreScoringFeatureHydrationFeatureMaps: Seq[FeatureMap] =
- getMergedPreScoringFeatureMap(ScoringPipelineConfig.resultStep, previousPipelineResult)
-
- val itemCandidates = executorResult.asInstanceOf[Seq[ItemCandidateWithDetails]]
- val finalFeatureMap = if (mergedPreScoringFeatureHydrationFeatureMaps.isEmpty) {
- scorerResults
- } else {
- scorerResults
- .zip(mergedPreScoringFeatureHydrationFeatureMaps).map {
- case (preScoringFeatureMap, scoringFeatureMap) =>
- preScoringFeatureMap ++ scoringFeatureMap
- }
- }
-
- val finalResults = itemCandidates.zip(finalFeatureMap).map {
- case (itemCandidate, featureMap) =>
- ScoredCandidateResult(itemCandidate.candidate.asInstanceOf[Candidate], featureMap)
- }
- previousPipelineResult.withResult(finalResults)
- }
- }
-
- val builtSteps = Seq(
- GatesStep,
- SelectorsStep,
- PreScoringFeatureHydrationPhase1Step,
- PreScoringFeatureHydrationPhase2Step,
- ScorersStep,
- ResultStep
- )
-
- /** The main execution logic for this Candidate Pipeline. */
- val finalArrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] =
- buildCombinedArrowFromSteps(
- steps = builtSteps,
- context = context,
- initialEmptyResult = ScoringPipelineResult.empty,
- stepsInOrderFromConfig = ScoringPipelineConfig.stepsInOrder
- )
-
- val configFromBuilder = config
- new ScoringPipeline[Query, Candidate] {
- override private[core] val config: ScoringPipelineConfig[Query, Candidate] = configFromBuilder
- override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] =
- finalArrow
- override val identifier: ScoringPipelineIdentifier = pipelineIdentifier
- override val alerts: Seq[Alert] = config.alerts
- override val children: Seq[Component] =
- allGates ++ config.preScoringFeatureHydrationPhase1 ++ config.preScoringFeatureHydrationPhase2 ++ config.scorers
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala
deleted file mode 100644
index 5b65d0738..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ScoringPipelineBuilderFactory @Inject() (
- gateExecutor: GateExecutor,
- selectorExecutor: SelectorExecutor,
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor,
- statsReceiver: StatsReceiver) {
-
- def get[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ]: ScoringPipelineBuilder[Query, Candidate] = {
- new ScoringPipelineBuilder[Query, Candidate](
- gateExecutor,
- selectorExecutor,
- candidateFeatureHydratorExecutor,
- statsReceiver
- )
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala
deleted file mode 100644
index d2b87e01b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.product_mixer.component_library.selector.InsertAppendResults
-import com.twitter.product_mixer.core.functional_component.common.AllPipelines
-import com.twitter.product_mixer.core.functional_component.common.alert.Alert
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineConfig
-import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.DeciderParam
-
-/**
- * This is the configuration necessary to generate a Scoring Pipeline. Product code should create a
- * ScoringPipelineConfig, and then use a ScoringPipelineBuilder to get the final ScoringPipeline which can
- * process requests.
- *
- * @tparam Query - The domain model for the query or request
- * @tparam Candidate the domain model for the candidate being scored
- */
-trait ScoringPipelineConfig[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]
- extends PipelineConfig {
-
- override val identifier: ScoringPipelineIdentifier
-
- /**
- * When these Params are defined, they will automatically be added as Gates in the pipeline
- * by the CandidatePipelineBuilder
- *
- * The enabled decider param can to be used to quickly disable a Candidate Pipeline via Decider
- */
- val enabledDeciderParam: Option[DeciderParam[Boolean]] = None
-
- /**
- * This supported client feature switch param can be used with a Feature Switch to control the
- * rollout of a new Candidate Pipeline from dogfood to experiment to production
- */
- val supportedClientParam: Option[FSParam[Boolean]] = None
-
- /** [[BaseGate]]s that are applied sequentially, the pipeline will only run if all the Gates are open */
- def gates: Seq[BaseGate[Query]] = Seq.empty
-
- /**
- * Logic for selecting which candidates to score. Note, this doesn't drop the candidates from
- * the final result, just whether to score it in this pipeline or not.
- */
- def selectors: Seq[Selector[Query]]
-
- /**
- * After selectors are run, you can fetch features for each candidate.
- * The existing features from previous hydrations are passed in as inputs. You are not expected to
- * put them into the resulting feature map yourself - they will be merged for you by the platform.
- */
- def preScoringFeatureHydrationPhase1: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] =
- Seq.empty
-
- /**
- * A second phase of feature hydration that can be run after selection and after the first phase
- * of pre-scoring feature hydration. You are not expected to put them into the resulting
- * feature map yourself - they will be merged for you by the platform.
- */
- def preScoringFeatureHydrationPhase2: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] =
- Seq.empty
-
- /**
- * Ranker Function for candidates. Scorers are executed in parallel.
- * Note: Order does not matter, this could be a Set if Set was covariant over it's type.
- */
- def scorers: Seq[Scorer[Query, Candidate]]
-
- /**
- * A pipeline can define a partial function to rescue failures here. They will be treated as failures
- * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here).
- */
- def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty
-
- /**
- * Alerts can be used to indicate the pipeline's service level objectives. Alerts and
- * dashboards will be automatically created based on this information.
- */
- val alerts: Seq[Alert] = Seq.empty
-
- /**
- * This method is used by the product mixer framework to build the pipeline.
- */
- private[core] final def build(
- parentComponentIdentifierStack: ComponentIdentifierStack,
- builder: ScoringPipelineBuilderFactory
- ): ScoringPipeline[Query, Candidate] =
- builder.get.build(parentComponentIdentifierStack, this)
-}
-
-object ScoringPipelineConfig extends PipelineConfigCompanion {
- def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- scorer: Scorer[Query, Candidate]
- ): ScoringPipelineConfig[Query, Candidate] = new ScoringPipelineConfig[Query, Candidate] {
- override val identifier: ScoringPipelineIdentifier = ScoringPipelineIdentifier(
- s"ScoreAll${scorer.identifier.name}")
-
- override val selectors: Seq[Selector[Query]] = Seq(InsertAppendResults(AllPipelines))
-
- override val scorers: Seq[Scorer[Query, Candidate]] = Seq(scorer)
- }
-
- val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates")
- val selectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("Selectors")
- val preScoringFeatureHydrationPhase1Step: PipelineStepIdentifier =
- PipelineStepIdentifier("PreScoringFeatureHydrationPhase1")
- val preScoringFeatureHydrationPhase2Step: PipelineStepIdentifier =
- PipelineStepIdentifier("PreScoringFeatureHydrationPhase2")
- val scorersStep: PipelineStepIdentifier = PipelineStepIdentifier("Scorers")
- val resultStep: PipelineStepIdentifier = PipelineStepIdentifier("Result")
-
- /** All the Steps which are executed by a [[ScoringPipeline]] in the order in which they are run */
- override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq(
- gatesStep,
- selectorsStep,
- preScoringFeatureHydrationPhase1Step,
- preScoringFeatureHydrationPhase2Step,
- scorersStep,
- resultStep
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala
deleted file mode 100644
index ca1585b4c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.scoring
-
-import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-
-/**
- * The Results of every step during the ScoringPipeline process. The end result contains
- * only the candidates that were actually scored (e.g, not dropped by a filter) with an updated,
- * combined feature map of all features that were passed in with the candidate plus all features
- * returned as part of scoring.
- */
-case class ScoringPipelineResult[Candidate <: UniversalNoun[Any]](
- gateResults: Option[GateExecutorResult],
- selectorResults: Option[SelectorExecutorResult],
- preScoringHydrationPhase1Result: Option[CandidateFeatureHydratorExecutorResult[Candidate]],
- preScoringHydrationPhase2Result: Option[CandidateFeatureHydratorExecutorResult[Candidate]],
- scorerResults: Option[CandidateFeatureHydratorExecutorResult[
- Candidate
- ]],
- failure: Option[PipelineFailure],
- result: Option[Seq[ScoredCandidateResult[Candidate]]])
- extends PipelineResult[Seq[ScoredCandidateResult[Candidate]]] {
- override val resultSize: Int = result.map(_.size).getOrElse(0)
-
- override def withFailure(
- failure: PipelineFailure
- ): ScoringPipelineResult[Candidate] =
- copy(failure = Some(failure))
- override def withResult(
- result: Seq[ScoredCandidateResult[Candidate]]
- ): ScoringPipelineResult[Candidate] =
- copy(result = Some(result))
-}
-
-object ScoringPipelineResult {
- def empty[Candidate <: UniversalNoun[Any]]: ScoringPipelineResult[Candidate] =
- ScoringPipelineResult(
- None,
- None,
- None,
- None,
- None,
- None,
- None
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD
deleted file mode 100644
index fe26c9f66..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator:decoration",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator:decoration",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala
deleted file mode 100644
index 9ff0ed803..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-
-trait HasAsyncFeatureMap[State] {
- def asyncFeatureMap: AsyncFeatureMap
-
- private[core] def addAsyncFeatureMap(newFeatureMap: AsyncFeatureMap): State
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala
deleted file mode 100644
index 85f2937c7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait HasCandidates[Candidate <: UniversalNoun[Any], T] {
- def candidates: Seq[Candidate]
- def updateCandidates(newCandidates: Seq[Candidate]): T
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala
deleted file mode 100644
index f91d17bb3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-
-trait HasCandidatesWithDetails[T] {
- def candidatesWithDetails: Seq[CandidateWithDetails]
- def updateCandidatesWithDetails(newCandidates: Seq[CandidateWithDetails]): T
-
- def updateDecorations(decoration: Seq[Decoration]): T
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala
deleted file mode 100644
index 1fa327e6b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-
-trait HasCandidatesWithFeatures[Candidate <: UniversalNoun[Any], T] {
- def candidatesWithFeatures: Seq[CandidateWithFeatures[Candidate]]
- def updateCandidatesWithFeatures(newCandidates: Seq[CandidateWithFeatures[Candidate]]): T
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala
deleted file mode 100644
index c22dbe11c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.service.ExecutorResult
-import scala.collection.immutable.ListMap
-
-trait HasExecutorResults[State] {
- // We use a list map to maintain the insertion order
- val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult]
- private[pipeline] def setExecutorResults(
- newMap: ListMap[PipelineStepIdentifier, ExecutorResult]
- ): State
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala
deleted file mode 100644
index 42f7f0062..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.timelines.configapi.Params
-
-trait HasParams {
- def params: Params
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala
deleted file mode 100644
index 89e9bd94e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait HasQuery[Query <: PipelineQuery, T] {
- def query: Query
- def updateQuery(query: Query): T
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala
deleted file mode 100644
index 9058f0561..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-
-trait HasRequest[TRequest <: Request] {
- def request: TRequest
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala
deleted file mode 100644
index 0c5f0dfef..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.state
-
-/**
- * Defines how to build a result from a pipeline state. Pipeline States should extend this and
- * implement [[buildResult]] which computes the final result from their current state.
- * @tparam Result Type of result
- */
-trait HasResult[+Result] {
- def buildResult(): Result
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD
deleted file mode 100644
index cbd8c036d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala
deleted file mode 100644
index 99aa9ae87..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step
-
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-
-/**
- * A Step within a Pipeline, a Step is a unitary phase within an entire chain that makes up a pipeline.
- * @tparam State The request domain model.
- * @tparam ExecutorConfig The configs that should be passed into the executor at build time.
- * @tparam ExecutorInput The input type that an executor takes at request time.
- * @tparam ExResult The result that a step's executor will return.
- * @tparam OutputState The final/updated state a step would output, this is typically taking the ExResult
- * and mutating/transforming the State.
- */
-trait Step[State, -Config, ExecutorInput, ExResult <: ExecutorResult] {
-
- /**
- * Adapt the state into the expected input for the Step's Arrow.
- *
- * @param state State object passed into the Step.
- * @param config The config object used to build the executor arrow or input.
- * @return ExecutorInput that is used in the arrow of the underlying executor.
- */
- def adaptInput(state: State, config: Config): ExecutorInput
-
- /**
- * The actual arrow to be executed for the step, taking in the adapted input from [[adaptInput]]
- * and returning the expected result.
- * @param config Runtime configurations to configure the arrow with.
- * @param context Context of Executor.
- */
- def arrow(
- config: Config,
- context: Executor.Context
- ): Arrow[ExecutorInput, ExResult]
-
- /**
- * Whether the step is considered a noop/empty based off of input being passed in. Empty
- * steps are skipped when being executed.
- */
- def isEmpty(config: Config): Boolean
-
- /**
- * Update the passed in state based off of the result from [[arrow]]
- * @param state State object passed into the Step.
- * @param executorResult Executor result returned from [[arrow]]
- * @param config The config object used to build the executor arrow or input.
- * @return Updated state object passed.
- */
- def updateState(state: State, executorResult: ExResult, config: Config): State
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala
deleted file mode 100644
index 9f0c787bb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.async_feature_map
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasAsyncFeatureMap
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor
-import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * Async Feature Hydrator Step, it takes an existing asyn feature map and executes any hydration
- * needed before the next step. The state object is responsible for keeping the updated query
- * with the updated feature map.
- *
- * @param asyncFeatureMapExecutor Async feature map executor
- *
- * @tparam Query Type of PipelineQuery domain model
- * @tparam State The pipeline state domain model.
- */
-case class AsyncFeatureMapStep[
- Query <: PipelineQuery,
- State <: HasQuery[Query, State] with HasAsyncFeatureMap[State]] @Inject() (
- asyncFeatureMapExecutor: AsyncFeatureMapExecutor)
- extends Step[
- State,
- AsyncFeatureMapStepConfig,
- AsyncFeatureMap,
- AsyncFeatureMapExecutorResults
- ] {
- override def isEmpty(config: AsyncFeatureMapStepConfig): Boolean = false
-
- override def adaptInput(
- state: State,
- config: AsyncFeatureMapStepConfig
- ): AsyncFeatureMap = state.asyncFeatureMap
-
- override def arrow(
- config: AsyncFeatureMapStepConfig,
- context: Executor.Context
- ): Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] =
- asyncFeatureMapExecutor.arrow(config.stepToHydrateFor, config.currentStep, context)
-
- override def updateState(
- state: State,
- executorResult: AsyncFeatureMapExecutorResults,
- config: AsyncFeatureMapStepConfig
- ): State = {
- val hydratedFeatureMap =
- executorResult.featureMapsByStep.getOrElse(config.stepToHydrateFor, FeatureMap.empty)
- if (hydratedFeatureMap.isEmpty) {
- state
- } else {
- val updatedFeatureMap = state.query.features
- .getOrElse(FeatureMap.empty) ++ hydratedFeatureMap
- state.updateQuery(
- state.query
- .withFeatureMap(updatedFeatureMap).asInstanceOf[Query])
- }
- }
-}
-
-case class AsyncFeatureMapStepConfig(
- stepToHydrateFor: PipelineStepIdentifier,
- currentStep: PipelineStepIdentifier)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel
deleted file mode 100644
index 144fc73d8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD
deleted file mode 100644
index a15f0c954..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala
deleted file mode 100644
index 94c11256d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.candidate_feature_hydrator
-
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A candidate level feature hydration step, it takes the input list of candidates and the given
- * hydrators and executes them. The [[State]] object is responsible for merging the resulting
- * feature maps with the hydrated ones in its updateCandidatesWithFeatures.
- *
- * @param candidateFeatureHydratorExecutor Hydrator Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam Candidate Type of Candidates to hydrate features for.
- * @tparam State The pipeline state domain model.
- */
-case class CandidateFeatureHydratorStep[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- State <: HasQuery[Query, State] with HasCandidatesWithFeatures[
- Candidate,
- State
- ]] @Inject() (
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor)
- extends Step[State, Seq[
- BaseCandidateFeatureHydrator[Query, Candidate, _]
- ], CandidateFeatureHydratorExecutor.Inputs[
- Query,
- Candidate
- ], CandidateFeatureHydratorExecutorResult[Candidate]] {
-
- override def adaptInput(
- state: State,
- config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] =
- CandidateFeatureHydratorExecutor.Inputs(state.query, state.candidatesWithFeatures)
-
- override def arrow(
- config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]],
- context: Executor.Context
- ): Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] = candidateFeatureHydratorExecutor.arrow(config, context)
-
- override def updateState(
- input: State,
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate],
- config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]]
- ): State = {
- val candidatesWithHydratedFeatures = executorResult.results
- if (candidatesWithHydratedFeatures.isEmpty) {
- input
- } else {
- input.updateCandidatesWithFeatures(candidatesWithHydratedFeatures)
- }
- }
-
- override def isEmpty(
- config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]]
- ): Boolean =
- config.isEmpty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel
deleted file mode 100644
index 933fd47a3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala
deleted file mode 100644
index 359ff64cd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.candidate_source
-
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor
-import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A candidate source step, which takes the query and gets csandidates from the candidate source.
- *
- * @param candidateSourceExecutor Candidate Source Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam Candidate Type of Candidates to filter
- * @tparam State The pipeline state domain model.
- */
-case class CandidateSourceStep[
- Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Candidate <: UniversalNoun[Any],
- State <: HasQuery[Query, State] with HasCandidatesWithFeatures[Candidate, State]] @Inject() (
- candidateSourceExecutor: CandidateSourceExecutor)
- extends Step[
- State,
- CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate],
- Query,
- CandidateSourceExecutorResult[
- Candidate
- ]
- ] {
- override def isEmpty(
- config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate]
- ): Boolean = false
-
- override def adaptInput(
- state: State,
- config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate]
- ): Query = state.query
-
- override def arrow(
- config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate],
- context: Executor.Context
- ): Arrow[Query, CandidateSourceExecutorResult[Candidate]] = candidateSourceExecutor.arrow(
- config.candidateSource,
- config.queryTransformer,
- config.resultTransformer,
- config.resultFeaturesTransformers,
- context
- )
-
- override def updateState(
- state: State,
- executorResult: CandidateSourceExecutorResult[Candidate],
- config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate]
- ): State = state
- .updateQuery(
- state.query
- .withFeatureMap(executorResult.candidateSourceFeatureMap).asInstanceOf[
- Query]).updateCandidatesWithFeatures(executorResult.candidates)
-}
-
-case class CandidateSourceConfig[
- Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Candidate <: UniversalNoun[Any]
-](
- candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult],
- queryTransformer: BaseCandidatePipelineQueryTransformer[
- Query,
- CandidateSourceQuery
- ],
- resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Candidate],
- resultFeaturesTransformers: Seq[CandidateFeatureTransformer[CandidateSourceResult]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel
deleted file mode 100644
index 88d9b3be9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala
deleted file mode 100644
index 9f77bd110..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.decorator
-
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor
-import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A candidate decoration step, which takes the query and candidates and outputs decorations for them
- *
- * @param candidateDecoratorExecutor Candidate Source Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam Candidate Type of Candidates to filter
- * @tparam State The pipeline state domain model.
- */
-case class DecoratorStep[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- State <: HasQuery[Query, State] with HasCandidatesWithDetails[
- State
- ] with HasCandidatesWithFeatures[
- Candidate,
- State
- ]] @Inject() (candidateDecoratorExecutor: CandidateDecoratorExecutor)
- extends Step[
- State,
- Option[CandidateDecorator[Query, Candidate]],
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- CandidateDecoratorExecutorResult
- ] {
-
- override def isEmpty(config: Option[CandidateDecorator[Query, Candidate]]): Boolean =
- config.isEmpty
-
- override def adaptInput(
- state: State,
- config: Option[CandidateDecorator[Query, Candidate]]
- ): (Query, Seq[CandidateWithFeatures[Candidate]]) =
- (state.query, state.candidatesWithFeatures)
-
- override def arrow(
- config: Option[CandidateDecorator[Query, Candidate]],
- context: Executor.Context
- ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] =
- candidateDecoratorExecutor.arrow(config, context)
-
- override def updateState(
- state: State,
- executorResult: CandidateDecoratorExecutorResult,
- config: Option[CandidateDecorator[Query, Candidate]]
- ): State = {
- state.updateDecorations(executorResult.result)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel
deleted file mode 100644
index 35b2606fe..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel
+++ /dev/null
@@ -1,30 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala
deleted file mode 100644
index 18fee29a8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.domain_marshaller
-
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A domain marshaller step, it takes the input list of candidates and the given
- * domain marshaller and executes its to return a marshalled result. The [[State]] object is
- * responsible for keeping a reference of the built Response.
- *
- * @param domainMarshallerExecutor Domain Marshaller executor.
- * @tparam Query Type of PipelineQuery domain model
- * @tparam ResponseType the domain marshalling type expected to be returned.
- * @tparam State The pipeline state domain model.
- */
-case class DomainMarshallerStep[
- Query <: PipelineQuery,
- ResponseType <: HasMarshalling,
- State <: HasQuery[Query, State] with HasCandidatesWithDetails[State]] @Inject() (
- domainMarshallerExecutor: DomainMarshallerExecutor)
- extends Step[State, DomainMarshaller[Query, ResponseType], DomainMarshallerExecutor.Inputs[
- Query
- ], DomainMarshallerExecutor.Result[ResponseType]] {
-
- override def isEmpty(config: DomainMarshaller[Query, ResponseType]): Boolean = false
-
- override def adaptInput(
- state: State,
- config: DomainMarshaller[Query, ResponseType]
- ): DomainMarshallerExecutor.Inputs[Query] =
- DomainMarshallerExecutor.Inputs(state.query, state.candidatesWithDetails)
-
- override def arrow(
- config: DomainMarshaller[Query, ResponseType],
- context: Executor.Context
- ): Arrow[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ResponseType]] =
- domainMarshallerExecutor.arrow(config, context)
-
- // Noop since the pipeline updates the executor results for us
- override def updateState(
- state: State,
- executorResult: DomainMarshallerExecutor.Result[ResponseType],
- config: DomainMarshaller[Query, ResponseType]
- ): State = state
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel
deleted file mode 100644
index c5c363f7b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala
deleted file mode 100644
index f8d9770e1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.filter
-
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A candidate filter step, it takes the input list of candidates and the given filter and applies
- * the filters on the candidates in sequence, returning the final kept candidates list to State.
- *
- * @param filterExecutor Filter Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam Candidate Type of Candidates to filter
- * @tparam State The pipeline state domain model.
- */
-case class FilterStep[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- State <: HasQuery[Query, State] with HasCandidatesWithFeatures[
- Candidate,
- State
- ]] @Inject() (filterExecutor: FilterExecutor)
- extends Step[State, Seq[
- Filter[Query, Candidate]
- ], (Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] {
-
- override def isEmpty(config: Seq[Filter[Query, Candidate]]): Boolean = config.isEmpty
-
- override def adaptInput(
- state: State,
- config: Seq[Filter[Query, Candidate]]
- ): (Query, Seq[CandidateWithFeatures[Candidate]]) =
- (state.query, state.candidatesWithFeatures)
-
- override def arrow(
- config: Seq[Filter[Query, Candidate]],
- context: Executor.Context
- ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] =
- filterExecutor.arrow(config, context)
-
- override def updateState(
- state: State,
- executorResult: FilterExecutorResult[Candidate],
- config: Seq[Filter[Query, Candidate]]
- ): State = {
- val keptCandidates = executorResult.result
- val candidatesMap = state.candidatesWithFeatures.map { candidatesWithFeatures =>
- candidatesWithFeatures.candidate -> candidatesWithFeatures
- }.toMap
- val newCandidates = keptCandidates.flatMap { candidate =>
- candidatesMap.get(candidate)
- }
- state.updateCandidatesWithFeatures(newCandidates)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD
deleted file mode 100644
index 5ea9ee1bb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala
deleted file mode 100644
index c100fb1ed..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.gate
-
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutor
-import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A gate step, it takes the query and the given gates and executes them. Gates do not update state
- * if they return continue, and throw an exception if any gate says stopped, thus no state changes
- * are expected in this step. The [[NewPipelineArrowBuilder]] and [[PipelineStep]] handle short
- * circuiting the pipeline's execution if this throws.
- *
- * @param gateExecutor Gate Executor for executing the gates
- * @tparam Query Type of PipelineQuery domain model
- * @tparam State The pipeline state domain model.
- */
-case class GateStep[Query <: PipelineQuery, State <: HasQuery[Query, State]] @Inject() (
- gateExecutor: GateExecutor)
- extends Step[State, Seq[BaseGate[Query]], Query, GateExecutorResult] {
-
- override def adaptInput(state: State, config: Seq[BaseGate[Query]]): Query = state.query
-
- override def arrow(
- config: Seq[BaseGate[Query]],
- context: Executor.Context
- ): Arrow[Query, GateExecutorResult] = gateExecutor.arrow(config, context)
-
- // Gate Executor is a noop, if it continues, the state isn't changed. If it stops the world,
- // an exception gets thrown.
- override def updateState(
- input: State,
- executorResult: GateExecutorResult,
- config: Seq[BaseGate[Query]]
- ): State = input
-
- override def isEmpty(config: Seq[BaseGate[Query]]): Boolean = config.isEmpty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel
deleted file mode 100644
index 1a727b523..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel
+++ /dev/null
@@ -1,29 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala
deleted file mode 100644
index bb152be5d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.group_results
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorInput
-import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A group results step, it takes the input list of candidates and decorations, and assembles
- * properly decorated candidates with details.
- *
- * @param groupResultsExecutor Group results executor
- * @tparam Candidate Type of candidates
- * @tparam State The pipeline state domain model.
- */
-case class GroupResultsStep[
- Candidate <: UniversalNoun[Any],
- State <: HasCandidatesWithDetails[State] with HasCandidatesWithFeatures[
- Candidate,
- State
- ]] @Inject() (
- groupResultsExecutor: GroupResultsExecutor)
- extends Step[State, CandidatePipelineContext, GroupResultsExecutorInput[
- Candidate
- ], GroupResultsExecutorResult] {
-
- override def isEmpty(config: CandidatePipelineContext): Boolean = false
- override def adaptInput(
- state: State,
- config: CandidatePipelineContext
- ): GroupResultsExecutorInput[Candidate] = {
- val presentationMap = state.candidatesWithDetails.flatMap { candidateWithDetails =>
- candidateWithDetails.presentation
- .map { presentation =>
- candidateWithDetails.getCandidate[UniversalNoun[Any]] -> presentation
- }
- }.toMap
- GroupResultsExecutorInput(state.candidatesWithFeatures, presentationMap)
- }
-
- override def arrow(
- config: CandidatePipelineContext,
- context: Executor.Context
- ): Arrow[GroupResultsExecutorInput[Candidate], GroupResultsExecutorResult] =
- groupResultsExecutor.arrow(
- config.candidatePipelineIdentifier,
- config.candidateSourceIdentifier,
- context)
-
- override def updateState(
- state: State,
- executorResult: GroupResultsExecutorResult,
- config: CandidatePipelineContext
- ): State = state.updateCandidatesWithDetails(executorResult.candidatesWithDetails)
-}
-
-case class CandidatePipelineContext(
- candidatePipelineIdentifier: CandidatePipelineIdentifier,
- candidateSourceIdentifier: CandidateSourceIdentifier)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel
deleted file mode 100644
index 94b17381a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel
+++ /dev/null
@@ -1,32 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = [
- "bazel-compatible",
- "bazel-only",
- ],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala
deleted file mode 100644
index c2bdb6ea1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.pipeline_executor
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.state.HasResult
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.pipeline.step.pipeline_selector.PipelineSelectorResult
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorRequest
-import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * Pipeline Execution step that takes a selected pipeline and executes it.
- *
- * @param pipelineExecutor Pipeline executor that executes the selected pipeline
- *
- * @tparam Query Pipeline query model with quality factor status
- * @tparam Result The expected result type
- * @tparam State The pipeline state domain model.
- */
-case class PipelineExecutorStep[
- Query <: PipelineQuery,
- Result,
- State <: HasQuery[Query, State] with HasExecutorResults[State] with HasResult[Result]] @Inject() (
- pipelineExecutor: PipelineExecutor)
- extends Step[
- State,
- PipelineExecutorStepConfig[Query, Result],
- PipelineExecutorRequest[Query],
- PipelineExecutorResult[Result]
- ] {
-
- override def isEmpty(config: PipelineExecutorStepConfig[Query, Result]): Boolean =
- false
-
- override def adaptInput(
- state: State,
- config: PipelineExecutorStepConfig[Query, Result]
- ): PipelineExecutorRequest[Query] = {
- val pipelineSelectorResult = state.executorResultsByPipelineStep
- .getOrElse(
- config.selectedPipelineResultIdentifier,
- throw PipelineFailure(
- IllegalStateFailure,
- "Missing Selected Pipeline in Pipeline Executor Step")).asInstanceOf[
- PipelineSelectorResult]
- PipelineExecutorRequest(state.query, pipelineSelectorResult.pipelineIdentifier)
- }
-
- override def arrow(
- config: PipelineExecutorStepConfig[Query, Result],
- context: Executor.Context
- ): Arrow[PipelineExecutorRequest[Query], PipelineExecutorResult[Result]] = pipelineExecutor.arrow(
- config.pipelinesByIdentifier,
- config.qualityFactorObserversByIdentifier,
- context
- )
-
- // Noop since the platform will add the final result to the executor result map then state
- // is responsible for reading it in [[WithResult]]
- override def updateState(
- state: State,
- executorResult: PipelineExecutorResult[Result],
- config: PipelineExecutorStepConfig[Query, Result]
- ): State = state
-}
-
-case class PipelineExecutorStepConfig[Query <: PipelineQuery, Result](
- pipelinesByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Result]],
- selectedPipelineResultIdentifier: PipelineStepIdentifier,
- qualityFactorObserversByIdentifier: Map[ComponentIdentifier, QualityFactorObserver])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD
deleted file mode 100644
index e0babba8b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala
deleted file mode 100644
index aa40d4829..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.pipeline_selector
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * Pipeline Selection step to decide which pipeline to execute. This step doesn't update state, as
- * the selected pipeline identifier is added to the executor results list map for later retrieval
- *
- * @tparam Query Pipeline query model
- * @tparam State The pipeline state domain model.
- */
-case class PipelineSelectorStep[Query <: PipelineQuery, State <: HasQuery[Query, State]] @Inject() (
-) extends Step[State, Query => ComponentIdentifier, Query, PipelineSelectorResult] {
- override def isEmpty(config: Query => ComponentIdentifier): Boolean = false
-
- override def adaptInput(
- state: State,
- config: Query => ComponentIdentifier
- ): Query = state.query
-
- override def arrow(
- config: Query => ComponentIdentifier,
- context: Executor.Context
- ): Arrow[Query, PipelineSelectorResult] = Arrow.map { query: Query =>
- PipelineSelectorResult(config(query))
- }
-
- // Noop since we keep the identifier in the executor results
- override def updateState(
- state: State,
- executorResult: PipelineSelectorResult,
- config: Query => ComponentIdentifier
- ): State = state
-}
-
-case class PipelineSelectorResult(pipelineIdentifier: ComponentIdentifier) extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel
deleted file mode 100644
index a220a9550..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel
+++ /dev/null
@@ -1,31 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = [
- "bazel-compatible",
- "bazel-only",
- ],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala
deleted file mode 100644
index 0d66a4b57..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.quality_factor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus
-import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * Quality Factor building step that builds up the state snapshot for a map of configs.
- *
- * @param statsReceiver Stats Receiver used to build finagle gauges for QF State
- *
- * @tparam Query Pipeline query model with quality factor status
- * @tparam State The pipeline state domain model.
- */
-case class QualityFactorStep[
- Query <: PipelineQuery with HasQualityFactorStatus,
- State <: HasQuery[Query, State]] @Inject() (
- statsReceiver: StatsReceiver)
- extends Step[
- State,
- QualityFactorStepConfig,
- Any,
- QualityFactorStepResult
- ] {
- override def isEmpty(config: QualityFactorStepConfig): Boolean =
- config.qualityFactorStatus.qualityFactorByPipeline.isEmpty
-
- override def adaptInput(
- state: State,
- config: QualityFactorStepConfig
- ): Any = ()
-
- override def arrow(
- config: QualityFactorStepConfig,
- context: Executor.Context
- ): Arrow[Any, QualityFactorStepResult] = {
- // We use provideGauge so these gauges live forever even without a reference.
- val currentValues = config.qualityFactorStatus.qualityFactorByPipeline.map {
- case (identifier, qualityFactor) =>
- // QF is a relative stat (since the parent pipeline is monitoring a child pipeline)
- val scopes = config.pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor"
- val currentValue = qualityFactor.currentValue.toFloat
- statsReceiver.provideGauge(scopes: _*) {
- currentValue
- }
- identifier -> currentValue
- }
- Arrow.value(QualityFactorStepResult(currentValues))
- }
-
- override def updateState(
- state: State,
- executorResult: QualityFactorStepResult,
- config: QualityFactorStepConfig
- ): State = state.updateQuery(
- state.query.withQualityFactorStatus(config.qualityFactorStatus).asInstanceOf[Query])
-}
-
-case class QualityFactorStepConfig(
- pipelineIdentifier: ComponentIdentifier,
- qualityFactorStatus: QualityFactorStatus)
-
-case class QualityFactorStepResult(currentValues: Map[ComponentIdentifier, Float])
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel
deleted file mode 100644
index 2ed3762c4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala
deleted file mode 100644
index 1b119fc2f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.query_feature_hydrator
-
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasAsyncFeatureMap
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A query level feature hydration step, it takes the input list of candidates and the given
- * hydrators and executes them. The [[State]] object is responsible for merging the resulting
- * feature maps with the hydrated ones in its updateCandidatesWithFeatures.
- *
- * @param queryFeatureHydratorExecutor Hydrator Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam State The pipeline state domain model.
- */
-case class QueryFeatureHydratorStep[
- Query <: PipelineQuery,
- State <: HasQuery[Query, State] with HasAsyncFeatureMap[State]] @Inject() (
- queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor)
- extends Step[State, QueryFeatureHydratorStepConfig[
- Query
- ], Query, QueryFeatureHydratorExecutor.Result] {
- override def isEmpty(config: QueryFeatureHydratorStepConfig[Query]): Boolean =
- config.hydrators.isEmpty
-
- override def adaptInput(state: State, config: QueryFeatureHydratorStepConfig[Query]): Query =
- state.query
-
- override def arrow(
- config: QueryFeatureHydratorStepConfig[Query],
- context: Executor.Context
- ): Arrow[Query, QueryFeatureHydratorExecutor.Result] =
- queryFeatureHydratorExecutor.arrow(
- config.hydrators,
- config.validPipelineStepIdentifiers,
- context)
-
- override def updateState(
- state: State,
- executorResult: QueryFeatureHydratorExecutor.Result,
- config: QueryFeatureHydratorStepConfig[Query]
- ): State = {
- val updatedQuery = state.query
- .withFeatureMap(executorResult.featureMap).asInstanceOf[Query]
- state
- .updateQuery(updatedQuery).addAsyncFeatureMap(executorResult.asyncFeatureMap)
- }
-}
-
-case class QueryFeatureHydratorStepConfig[Query <: PipelineQuery](
- hydrators: Seq[BaseQueryFeatureHydrator[Query, _]],
- validPipelineStepIdentifiers: Set[PipelineStepIdentifier])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel
deleted file mode 100644
index dd63b24f6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel
+++ /dev/null
@@ -1,29 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = [
- "bazel-compatible",
- "bazel-only",
- ],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala
deleted file mode 100644
index 37814714b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.query_transformer
-
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasParams
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.state.HasRequest
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import com.twitter.timelines.configapi.Params
-
-/**
- * Query Transformation Step that takes an incoming thrift request model object and returns a
- * pipeline query. The pipeline state is responsible for keeping the updated query.
- *
- * @tparam TRequest Thrift request domain model
- * @tparam Query PipelineQuery type to transform to h
- * @tparam State The request domain model
- */
-case class QueryTransformerStep[
- TRequest <: Request,
- Query <: PipelineQuery,
- State <: HasQuery[Query, State] with HasRequest[TRequest] with HasParams
-]() extends Step[State, (TRequest, Params) => Query, (TRequest, Params), QueryTransformerResult[
- Query
- ]] {
-
- override def isEmpty(config: (TRequest, Params) => Query): Boolean = false
-
- override def arrow(
- config: (TRequest, Params) => Query,
- context: Executor.Context
- ): Arrow[(TRequest, Params), QueryTransformerResult[Query]] = Arrow.map {
- case (request: TRequest @unchecked, params: Params) =>
- QueryTransformerResult(config(request, params))
- }
-
- override def updateState(
- state: State,
- executorResult: QueryTransformerResult[Query],
- config: (TRequest, Params) => Query
- ): State = state.updateQuery(executorResult.query)
-
- override def adaptInput(
- state: State,
- config: (TRequest, Params) => Query
- ): (TRequest, Params) = (state.request, state.params)
-}
-
-case class QueryTransformerResult[Query <: PipelineQuery](query: Query) extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD
deleted file mode 100644
index 105cd49a1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala
deleted file mode 100644
index 938b18d62..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.scorer
-
-import com.twitter.product_mixer.core.functional_component.scorer.Scorer
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A scoring step, it takes the input list of candidates and the given
- * scorers and executes them. The [[State]] object is responsible for merging the resulting
- * feature maps with the scored ones in its updateCandidatesWithFeatures.
- *
- * @param candidateFeatureHydratorExecutor Hydrator Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam Candidate Type of Candidates to hydrate features for.
- * @tparam State The pipeline state domain model.
- */
-case class ScorerStep[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any],
- State <: HasQuery[Query, State] with HasCandidatesWithFeatures[
- Candidate,
- State
- ]] @Inject() (
- candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor)
- extends Step[State, Seq[
- Scorer[Query, Candidate]
- ], CandidateFeatureHydratorExecutor.Inputs[
- Query,
- Candidate
- ], CandidateFeatureHydratorExecutorResult[Candidate]] {
-
- override def adaptInput(
- state: State,
- config: Seq[Scorer[Query, Candidate]]
- ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] =
- CandidateFeatureHydratorExecutor.Inputs(state.query, state.candidatesWithFeatures)
-
- override def arrow(
- config: Seq[Scorer[Query, Candidate]],
- context: Executor.Context
- ): Arrow[
- CandidateFeatureHydratorExecutor.Inputs[Query, Candidate],
- CandidateFeatureHydratorExecutorResult[Candidate]
- ] = candidateFeatureHydratorExecutor.arrow(config, context)
-
- override def updateState(
- input: State,
- executorResult: CandidateFeatureHydratorExecutorResult[Candidate],
- config: Seq[Scorer[Query, Candidate]]
- ): State = {
- val resultCandidates = executorResult.results
- if (resultCandidates.isEmpty) {
- input
- } else {
- input.updateCandidatesWithFeatures(resultCandidates)
- }
- }
-
- override def isEmpty(config: Seq[Scorer[Query, Candidate]]): Boolean =
- config.isEmpty
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD
deleted file mode 100644
index 4479122cd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD
+++ /dev/null
@@ -1,36 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala
deleted file mode 100644
index bc74d2d2b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.selector
-
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A selection step, it takes the input list of candidates with details and the given
- * selectors and executes them to decide which candidates should be selected.
- *
- * @param selectorExecutor Selector Executor
- * @tparam Query Type of PipelineQuery domain model
- * @tparam State The pipeline state domain model.
- */
-case class SelectorStep[
- Query <: PipelineQuery,
- State <: HasQuery[Query, State] with HasCandidatesWithDetails[State]] @Inject() (
- selectorExecutor: SelectorExecutor)
- extends Step[State, Seq[
- Selector[Query]
- ], SelectorExecutor.Inputs[
- Query
- ], SelectorExecutorResult] {
-
- override def adaptInput(
- state: State,
- config: Seq[Selector[Query]]
- ): SelectorExecutor.Inputs[Query] =
- SelectorExecutor.Inputs(state.query, state.candidatesWithDetails)
-
- override def arrow(
- config: Seq[Selector[Query]],
- context: Executor.Context
- ): Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] =
- selectorExecutor.arrow(config, context)
-
- override def updateState(
- input: State,
- executorResult: SelectorExecutorResult,
- config: Seq[Selector[Query]]
- ): State = input.updateCandidatesWithDetails(executorResult.selectedCandidates)
-
- // Selection is a bit different to other steps (i.e, other steps, empty means don't change anything)
- // where an empty selection list drops all candidates.
- override def isEmpty(config: Seq[Selector[Query]]): Boolean = false
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel
deleted file mode 100644
index fb9d33c98..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel
+++ /dev/null
@@ -1,32 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala
deleted file mode 100644
index 36e72cff6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.side_effect
-
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.state.HasQuery
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor
-import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A side effect step, it takes the input list of side effects and and executes them.
- *
- * @param sideEffectExecutor Side Effect Executor
- *
- * @tparam Query Type of PipelineQuery domain model
- * @tparam DomainResultType Domain Marshaller result type
- * @tparam State The pipeline state domain model.
- */
-case class SideEffectStep[
- Query <: PipelineQuery,
- DomainResultType <: HasMarshalling,
- State <: HasQuery[Query, State] with HasExecutorResults[State]] @Inject() (
- sideEffectExecutor: PipelineResultSideEffectExecutor)
- extends Step[
- State,
- PipelineStepConfig[Query, DomainResultType],
- PipelineResultSideEffect.Inputs[
- Query,
- DomainResultType
- ],
- PipelineResultSideEffectExecutor.Result
- ] {
- override def isEmpty(config: PipelineStepConfig[Query, DomainResultType]): Boolean =
- config.sideEffects.isEmpty
-
- override def adaptInput(
- state: State,
- config: PipelineStepConfig[Query, DomainResultType]
- ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = {
- val selectorResults = state.executorResultsByPipelineStep
- .getOrElse(
- config.selectorStepIdentifier,
- throw PipelineFailure(
- IllegalStateFailure,
- "Missing Selector Result in Side Effect Step")).asInstanceOf[SelectorExecutorResult]
-
- val domainMarshallerResult = state.executorResultsByPipelineStep
- .getOrElse(
- config.domainMarshallerStepIdentifier,
- throw PipelineFailure(
- IllegalStateFailure,
- "Missing Domain Marshaller Result in Side Effect Step")).asInstanceOf[
- DomainMarshallerExecutor.Result[DomainResultType]]
-
- PipelineResultSideEffect.Inputs(
- query = state.query,
- selectedCandidates = selectorResults.selectedCandidates,
- remainingCandidates = selectorResults.remainingCandidates,
- droppedCandidates = selectorResults.droppedCandidates,
- response = domainMarshallerResult.result
- )
- }
-
- override def arrow(
- config: PipelineStepConfig[Query, DomainResultType],
- context: Executor.Context
- ): Arrow[
- PipelineResultSideEffect.Inputs[Query, DomainResultType],
- PipelineResultSideEffectExecutor.Result
- ] = sideEffectExecutor.arrow(config.sideEffects, context)
-
- override def updateState(
- state: State,
- executorResult: PipelineResultSideEffectExecutor.Result,
- config: PipelineStepConfig[Query, DomainResultType]
- ): State = state
-}
-
-/**
- * Wrapper case class containing side effects to be executed and other information needed to execute
- * @param sideEffects The side effects to execute.
- * @param selectorStepIdentifier The identifier of the selector step in the parent
- * pipeline to get selection results from.
- * @param domainMarshallerStepIdentifier The identifier of the domain marshaller step in the parent
- * pipeline to get domain marshalled results from.
- *
- * @tparam Query Type of PipelineQuery domain model
- * @tparam DomainResultType Domain Marshaller result type
- */
-case class PipelineStepConfig[Query <: PipelineQuery, DomainResultType <: HasMarshalling](
- sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]],
- selectorStepIdentifier: PipelineStepIdentifier,
- domainMarshallerStepIdentifier: PipelineStepIdentifier)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel
deleted file mode 100644
index 7b097b33f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel
+++ /dev/null
@@ -1,31 +0,0 @@
-scala_library(
- sources = [
- "*.scala",
- ],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala
deleted file mode 100644
index 577df3fdd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.twitter.product_mixer.core.pipeline.step.transport_marshaller
-
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults
-import com.twitter.product_mixer.core.pipeline.step.Step
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-
-/**
- * A transport marshaller step, it takes domain marshalled result as input and returns trasnport
- * ready marshalled object.
- * The [[State]] object is responsible for keeping a reference of the built marshalled response.
- *
- * @param transportMarshallerExecutor Domain Marshaller executor.
- * @tparam Query Type of PipelineQuery domain model
- * @tparam DomainResponseType the domain marshalling type used as input
- * @tparam TransportResponseType the expected returned transport type
- * @tparam State The pipeline state domain model.
- */
-case class TransportMarshallerStep[
- DomainResponseType <: HasMarshalling,
- TransportResponseType,
- State <: HasExecutorResults[State]] @Inject() (
- transportMarshallerExecutor: TransportMarshallerExecutor)
- extends Step[
- State,
- TransportMarshallerConfig[DomainResponseType, TransportResponseType],
- TransportMarshallerExecutor.Inputs[DomainResponseType],
- TransportMarshallerExecutor.Result[TransportResponseType]
- ] {
-
- override def isEmpty(
- config: TransportMarshallerConfig[DomainResponseType, TransportResponseType]
- ): Boolean = false
-
- override def adaptInput(
- state: State,
- config: TransportMarshallerConfig[DomainResponseType, TransportResponseType]
- ): TransportMarshallerExecutor.Inputs[DomainResponseType] = {
- val domainMarshallerResult = state.executorResultsByPipelineStep
- .getOrElse(
- config.domainMarshallerStepIdentifier,
- throw PipelineFailure(
- IllegalStateFailure,
- "Missing Domain Marshaller in Transport Marshaller Step")).asInstanceOf[
- DomainMarshallerExecutor.Result[DomainResponseType]]
- TransportMarshallerExecutor.Inputs(domainMarshallerResult.result)
- }
-
- // Noop as platform updates executor result
- override def updateState(
- state: State,
- executorResult: TransportMarshallerExecutor.Result[TransportResponseType],
- config: TransportMarshallerConfig[DomainResponseType, TransportResponseType]
- ): State = state
-
- override def arrow(
- config: TransportMarshallerConfig[DomainResponseType, TransportResponseType],
- context: Executor.Context
- ): Arrow[TransportMarshallerExecutor.Inputs[
- DomainResponseType
- ], TransportMarshallerExecutor.Result[TransportResponseType]] =
- transportMarshallerExecutor.arrow(config.transportMarshaller, context)
-
-}
-
-case class TransportMarshallerConfig[DomainResponseType <: HasMarshalling, TransportResponseType](
- transportMarshaller: TransportMarshaller[DomainResponseType, TransportResponseType],
- domainMarshallerStepIdentifier: PipelineStepIdentifier)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD
deleted file mode 100644
index cc258ffe8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer",
- "stitch/stitch-core",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala
deleted file mode 100644
index c390b599e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.twitter.product_mixer.core.product
-
-import com.twitter.product_mixer.core.functional_component.configapi.registry.ParamConfig
-import com.twitter.servo.decider.DeciderKeyName
-import com.twitter.timelines.configapi.FSParam
-import com.twitter.timelines.configapi.decider.BooleanDeciderParam
-
-trait ProductParamConfig extends ParamConfig with ProductParamConfigBuilder {
-
- /**
- * This enabled decider param can to be used to quickly disable a Product via Decider
- *
- * This value must correspond to the deciders configured in the `resources/config/decider.yml` file
- */
- val enabledDeciderKey: DeciderKeyName
-
- /**
- * This supported client feature switch param can be used with a Feature Switch to control the
- * rollout of a new Product from dogfood to experiment to production
- *
- * FeatureSwitches are configured by defining both a [[com.twitter.timelines.configapi.Param]] in code
- * and in an associated `.yml` file in the __config repo__.
- *
- * The `.yml` file path is determined by the `feature_switches_path` in your aurora file and tge Product name
- * so the resulting path in the __config repo__ is essentially `s"{feature_switches_path}/{snakeCase(Product.identifier)}"`
- */
- val supportedClientFSName: String
-
- object EnabledDeciderParam extends BooleanDeciderParam(enabledDeciderKey)
-
- object SupportedClientParam
- extends FSParam(
- name = supportedClientFSName,
- default = false
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala
deleted file mode 100644
index 0d3490ebe..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.product
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.configapi.registry.ParamConfigBuilder
-import com.twitter.servo.decider.DeciderGateBuilder
-import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil
-import com.twitter.timelines.configapi.OptionalOverride
-import com.twitter.timelines.configapi.decider.DeciderUtils
-
-trait ProductParamConfigBuilder extends ParamConfigBuilder {
- productParamConfig: ProductParamConfig =>
-
- override def build(
- deciderGateBuilder: DeciderGateBuilder,
- statsReceiver: StatsReceiver
- ): Seq[OptionalOverride[_]] = {
- DeciderUtils.getBooleanDeciderOverrides(deciderGateBuilder, EnabledDeciderParam) ++
- FeatureSwitchOverrideUtil.getBooleanFSOverrides(SupportedClientParam) ++
- super.build(deciderGateBuilder, statsReceiver)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD
deleted file mode 100644
index 998a18e9d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- ],
- exports = [
- "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala
deleted file mode 100644
index a4ae726dd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.product.guice
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.google.inject.Key
-
-/**
- * A specialization of SimpleScope - a simple Guice Scope that takes an initial Product Mixer Product as a key
- */
-class ProductScope extends SimpleScope {
- def let[T](product: Product)(f: => T): T = super.let(Map(Key.get(classOf[Product]) -> product))(f)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala
deleted file mode 100644
index 8345f166e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.twitter.product_mixer.core.product.guice
-
-import com.google.inject.Provides
-import com.twitter.inject.TwitterModule
-import com.twitter.product_mixer.core.product.guice.scope.ProductScoped
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import javax.inject.Singleton
-
-/**
- * Registers the @ProductScoped scope.
- *
- * See https://github.com/google/guice/wiki/CustomScopes#registering-the-scope
- */
-@Singleton
-class ProductScopeModule extends TwitterModule {
-
- val productScope: ProductScope = new ProductScope
-
- override def configure(): Unit = {
- bindScope(classOf[ProductScoped], productScope)
-
- bind[Product].toProvider(SimpleScope.SEEDED_KEY_PROVIDER).in(classOf[ProductScoped])
- }
-
- @Provides
- def providesProductScope(): ProductScope = productScope
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala
deleted file mode 100644
index ccbf77121..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.twitter.product_mixer.core.product.guice
-
-import com.google.inject.Key
-import com.google.inject.OutOfScopeException
-import com.google.inject.Provider
-import com.google.inject.Scope
-import com.google.inject.Scopes
-import com.twitter.util.Local
-import scala.collection.concurrent
-import scala.collection.mutable
-
-/**
- * A scala-esque implementation of SimpleScope: https://github.com/google/guice/wiki/CustomScopes#implementing-scope
- *
- * Scopes the execution of a single block of code via `let`
- */
-class SimpleScope extends Scope {
-
- private val values = new Local[concurrent.Map[Key[_], Any]]()
-
- /**
- * Execute a block with a fresh scope.
- *
- * You can optionally supply a map of initialObjects to 'seed' the new scope.
- */
- def let[T](initialObjects: Map[Key[_], Any] = Map.empty)(f: => T): T = {
- val newMap: concurrent.Map[Key[_], Any] = concurrent.TrieMap.empty
-
- initialObjects.foreach { case (key, value) => newMap.put(key, value) }
-
- values.let(newMap)(f)
- }
-
- override def scope[T](
- key: Key[T],
- unscoped: Provider[T]
- ): Provider[T] = () => {
- val scopedObjects: mutable.Map[Key[T], Any] = getScopedObjectMap(key)
-
- scopedObjects
- .get(key).map(_.asInstanceOf[T]).getOrElse {
- val objectFromUnscoped: T = unscoped.get()
-
- if (Scopes.isCircularProxy(objectFromUnscoped)) {
- objectFromUnscoped // Don't remember proxies
- } else {
- scopedObjects.put(key, objectFromUnscoped)
- objectFromUnscoped
- }
- }
- }
-
- def getScopedObjectMap[T](key: Key[T]): concurrent.Map[Key[T], Any] = {
- values()
- .getOrElse(
- throw new OutOfScopeException(s"Cannot access $key outside of a scoping block")
- ).asInstanceOf[concurrent.Map[Key[T], Any]]
- }
-}
-
-object SimpleScope {
-
- val SEEDED_KEY_PROVIDER: Provider[Nothing] = () =>
- throw new IllegalStateException(
- """If you got here then it means that your code asked for scoped object which should have
- | been explicitly seeded in this scope by calling SimpleScope.seed(),
- | but was not.""".stripMargin)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD
deleted file mode 100644
index 9ecf4adca..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala
deleted file mode 100644
index 089aaea5e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.product.registry
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.servo.decider.DeciderGateBuilder
-import com.twitter.timelines.configapi.BaseConfigBuilder
-import com.twitter.timelines.configapi.Config
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class ProductParamRegistry @Inject() (
- productPipelineRegistryConfig: ProductPipelineRegistryConfig,
- deciderGateBuilder: DeciderGateBuilder,
- statsReceiver: StatsReceiver) {
-
- def build(): Seq[Config] = {
- val productConfigs = productPipelineRegistryConfig.productPipelineConfigs.map {
- productPipelineConfig =>
- BaseConfigBuilder(
- productPipelineConfig.paramConfig.build(deciderGateBuilder, statsReceiver))
- .build(productPipelineConfig.paramConfig.getClass.getSimpleName)
- }
-
- productConfigs
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala
deleted file mode 100644
index e04322f6a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala
+++ /dev/null
@@ -1,189 +0,0 @@
-package com.twitter.product_mixer.core.product.registry
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.RootIdentifier
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.product.ProductPipeline
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineBuilderFactory
-import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry
-import com.twitter.product_mixer.core.service.component_registry.ComponentRegistrySnapshot
-import com.twitter.product_mixer.shared_library.observer.Observer
-import com.twitter.util.Try
-import com.twitter.util.Var
-import com.twitter.util.logging.Logging
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.reflect.runtime.universe._
-
-@Singleton
-class ProductPipelineRegistry @Inject() (
- componentRegistry: ComponentRegistry,
- productPipelineRegistryConfig: ProductPipelineRegistryConfig,
- productPipelineBuilderFactory: ProductPipelineBuilderFactory,
- statsReceiver: StatsReceiver)
- extends Logging {
-
- private val rootIdentifierStack = ComponentIdentifierStack(RootIdentifier())
-
- private val rebuildObserver =
- Observer.function[Unit](statsReceiver, "ProductPipelineRegistry", "rebuild")
-
- /**
- * Internal state of ProductPipelineRegistry.
- *
- * Build once on startup, and later whenever `rebuild()` is called.
- */
- private[this] val productPipelineByProduct =
- Var[Map[Product, ProductPipeline[_ <: Request, _]]](buildProductPipelineByProduct())
-
- /**
- * Triggers a rebuild of the ProductPipelineRegistry and also the ComponentRegistry
- *
- * Failed rebuilds will throw an exception - likely one of the listed ones - and the product
- * registry and component registry will not be modified.
- *
- * @throws MultipleProductPipelinesForAProductException
- * @throws ComponentIdentifierCollisionException
- * @throws ChildComponentCollisionException
- */
- private[core] def rebuild(): Unit = {
- Try {
- rebuildObserver {
- productPipelineByProduct.update(buildProductPipelineByProduct())
- }
- }.onFailure { ex =>
- error("Failed to rebuild ProductPipelineRegistry", ex)
- }.get()
- }
-
- /**
- * register the provided pipeline recursively register all of it's children components
- * that are added to the [[Pipeline]]'s [[Pipeline.children]]
- */
- private def registerPipelineAndChildren(
- componentRegistrySnapshot: ComponentRegistrySnapshot,
- pipeline: Pipeline[_, _],
- parentIdentifierStack: ComponentIdentifierStack
- ): Unit = {
- val identifierStackString =
- s"${parentIdentifierStack.componentIdentifiers.reverse.mkString("\t->\t")}\t->\t${pipeline.identifier}"
- info(identifierStackString)
-
- componentRegistrySnapshot.register(
- component = pipeline,
- parentIdentifierStack = parentIdentifierStack)
-
- val identifierStackWithCurrentPipeline = parentIdentifierStack.push(pipeline.identifier)
- pipeline.children.foreach {
- case childPipeline: Pipeline[_, _] =>
- info(s"$identifierStackString\t->\t${childPipeline.identifier}")
- registerPipelineAndChildren(
- componentRegistrySnapshot,
- childPipeline,
- identifierStackWithCurrentPipeline)
- case component =>
- info(s"$identifierStackString\t->\t${component.identifier}")
- componentRegistrySnapshot.register(
- component = component,
- parentIdentifierStack = identifierStackWithCurrentPipeline)
- }
- }
-
- /*
- * Internal method (not for callers outside of this class, see rebuild() for those)
- *
- * Produces an updated Map[Product, ProductPipeline] and also refreshes the global component registry
- */
- private[this] def buildProductPipelineByProduct(
- ): Map[Product, ProductPipeline[_ <: Request, _]] = {
-
- // Build a new component registry snapshot.
- val newComponentRegistry = new ComponentRegistrySnapshot()
-
- info(
- "Registering all products, pipelines, and components (this may be helpful if you encounter dependency injection errors)")
- info("debug details are in the form of `parent -> child`")
-
- // handle the case of multiple ProductPipelines having the same product
- checkForAndThrowMultipleProductPipelinesForAProduct()
-
- // Build a Map[Product, ProductPipeline], registering everything in the new component registry recursively
- val pipelinesByProduct: Map[Product, ProductPipeline[_ <: Request, _]] =
- productPipelineRegistryConfig.productPipelineConfigs.map { productPipelineConfig =>
- val product = productPipelineConfig.product
- info(s"Recursively registering ${product.identifier}")
-
- // gets the ComponentIdentifierStack without the RootIdentifier since
- // we don't want RootIdentifier to show up in stats or errors
- val productPipeline =
- productPipelineBuilderFactory.get.build(
- ComponentIdentifierStack(product.identifier),
- productPipelineConfig)
-
- // gets RootIdentifier so we can register Products under the correct hierarchy
- newComponentRegistry.register(product, rootIdentifierStack)
- registerPipelineAndChildren(
- newComponentRegistry,
- productPipeline,
- rootIdentifierStack.push(product.identifier))
-
- // In addition to registering the component in the main registry, we want to maintain a map of
- // product to the product pipeline to allow for O(1) lookup by product on the request hot path
- product -> productPipeline
- }.toMap
-
- info(
- s"Successfully registered ${newComponentRegistry.getAllRegisteredComponents
- .count(_.identifier.isInstanceOf[ProductIdentifier])} products and " +
- s"${newComponentRegistry.getAllRegisteredComponents.length} " +
- s"components total, query the component registry endpoint for details")
-
- componentRegistry.set(newComponentRegistry)
-
- pipelinesByProduct
- }
-
- // handle the case of multiple ProductPipelines having the same product
- private def checkForAndThrowMultipleProductPipelinesForAProduct(): Unit = {
- productPipelineRegistryConfig.productPipelineConfigs.groupBy(_.product.identifier).foreach {
- case (product, productPipelines) if productPipelines.length != 1 =>
- throw new MultipleProductPipelinesForAProductException(
- product,
- productPipelines.map(_.identifier))
- case _ =>
- }
- }
-
- def getProductPipeline[MixerRequest <: Request: TypeTag, ResponseType: TypeTag](
- product: Product
- ): ProductPipeline[MixerRequest, ResponseType] = {
- // Check and cast the bounded existential types to the concrete types
- (typeOf[MixerRequest], typeOf[ResponseType]) match {
- case (req, res) if req =:= typeOf[MixerRequest] && res =:= typeOf[ResponseType] =>
- productPipelineByProduct.sample
- .getOrElse(product, throw new ProductNotFoundException(product))
- .asInstanceOf[ProductPipeline[MixerRequest, ResponseType]]
- case _ =>
- throw new UnknownPipelineResponseException(product)
- }
- }
-}
-
-class ProductNotFoundException(product: Product)
- extends RuntimeException(s"No Product found for $product")
-
-class UnknownPipelineResponseException(product: Product)
- extends RuntimeException(s"Unknown pipeline response for $product")
-
-class MultipleProductPipelinesForAProductException(
- product: ProductIdentifier,
- pipelineIdentifiers: Seq[ProductPipelineIdentifier])
- extends IllegalStateException(s"Multiple ProductPipelines found for $product, found " +
- s"${pipelineIdentifiers
- .map(productPipelineIdentifier => s"$productPipelineIdentifier from ${productPipelineIdentifier.file}")
- .mkString(", ")} ")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala
deleted file mode 100644
index bfa13c1c5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.product.registry
-
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineConfig
-
-trait ProductPipelineRegistryConfig {
- def productPipelineConfigs: Seq[ProductPipelineConfig[_ <: Request, _ <: PipelineQuery, _]]
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD
deleted file mode 100644
index 758b66385..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finagle/finagle-mux/src/main/scala",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "servo/util",
- "stitch/stitch-core",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala
deleted file mode 100644
index d94accb8f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-/**
- * Provides a way to apply inclusive min/max bounds to a given value.
- */
-case class Bounds[T](minInclusive: T, maxInclusive: T)(implicit ordering: Ordering[T]) {
-
- def apply(value: T): T = ordering.min(maxInclusive, ordering.max(minInclusive, value))
-
- def isWithin(value: T): Boolean =
- ordering.gteq(value, minInclusive) && ordering.lteq(value, maxInclusive)
-
- def throwIfOutOfBounds(value: T, messagePrefix: String): Unit =
- require(isWithin(value), s"$messagePrefix: value must be within $toString")
-
- override def toString: String = s"[$minInclusive, $maxInclusive]"
-}
-
-object BoundsWithDefault {
- def apply[T](
- minInclusive: T,
- maxInclusive: T,
- default: T
- )(
- implicit ordering: Ordering[T]
- ): BoundsWithDefault[T] = BoundsWithDefault(Bounds(minInclusive, maxInclusive), default)
-}
-
-case class BoundsWithDefault[T](bounds: Bounds[T], default: T)(implicit ordering: Ordering[T]) {
- bounds.throwIfOutOfBounds(default, "default")
-
- def apply(valueOpt: Option[T]): T = valueOpt.map(bounds.apply).getOrElse(default)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala
deleted file mode 100644
index 9750f21f6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.util.Duration
-import com.twitter.util.Stopwatch
-
-case class LinearLatencyQualityFactor(
- override val config: LinearLatencyQualityFactorConfig)
- extends QualityFactor[Duration] {
-
- private val delayedUntilInMillis = Stopwatch.timeMillis() + config.initialDelay.inMillis
-
- private var state: Double = config.qualityFactorBounds.default
-
- override def currentValue: Double = state
-
- override def update(latency: Duration): Unit = {
- if (Stopwatch.timeMillis() >= delayedUntilInMillis) {
- if (latency > config.targetLatency) {
- adjustState(getNegativeDelta)
- } else {
- adjustState(config.delta)
- }
- }
- }
-
- override def buildObserver(): QualityFactorObserver = LinearLatencyQualityFactorObserver(this)
-
- private def getNegativeDelta: Double =
- -config.delta * config.targetLatencyPercentile / (100.0 - config.targetLatencyPercentile)
-
- private def adjustState(delta: Double): Unit = {
- state = config.qualityFactorBounds.bounds(state + delta)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala
deleted file mode 100644
index bd5931d80..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.util.Duration
-import com.twitter.util.Try
-
-case class LinearLatencyQualityFactorObserver(
- override val qualityFactor: LinearLatencyQualityFactor)
- extends QualityFactorObserver {
-
- override def apply(result: Try[_], latency: Duration): Unit = {
- result
- .onSuccess(_ => qualityFactor.update(latency))
- .onFailure {
- case t if qualityFactor.config.ignorableFailures.isDefinedAt(t) => ()
- case _ => qualityFactor.update(Duration.Top)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala
deleted file mode 100644
index 7c65656f7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-/**
- * [[QualityFactor]] is an abstract number that enables a feedback loop to control operation costs and ultimately
- * maintain the operation success rate. Abstractly, if operations/calls are too expensive (such as high
- * latencies), the quality factor should go down, which helps future calls to ease their demand/load (such as
- * reducing request width); if ops/calls are fast, the quality factor should go up, so we can incur more load.
- *
- * @note to avoid overhead the underlying state may sometimes not be synchronized.
- * If a part of an application is unhealthy, it will likely be unhealthy for all threads,
- * it will eventually result in a close-enough quality factor value for all thread's view of the state.
- *
- * In extremely low volume scenarios such as manual testing in a development environment,
- * it's possible that different threads will have vastly different views of the underling state,
- * but in practice, in production systems, they will be close-enough.
- */
-trait QualityFactor[Input] { self =>
-
- /** get the current [[QualityFactor]]'s value */
- def currentValue: Double
-
- def config: QualityFactorConfig
-
- /** update of the current `factor` value */
- def update(input: Input): Unit
-
- /** a [[QualityFactorObserver]] for this [[QualityFactor]] */
- def buildObserver(): QualityFactorObserver
-
- override def toString: String = {
- self.getClass.getSimpleName.stripSuffix("$")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala
deleted file mode 100644
index e0ba6f465..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClientFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig.defaultIgnorableFailures
-import com.twitter.servo.util.CancelledExceptionExtractor
-import com.twitter.util.Duration
-import com.twitter.conversions.DurationOps.RichDuration
-
-/**
- * Quality factor is an abstract number that enables a feedback loop to control operation costs and ultimately
- * maintain the operation success rate. Abstractly, if operations/calls are too expensive (such as high
- * latencies), the quality factor should go down, which helps future calls to ease their demand/load (such as
- * reducing request width); if ops/calls are fast, the quality factor should go up, so we can incur more load.
- */
-sealed trait QualityFactorConfig {
-
- /**
- * specifies the quality factor min and max bounds and default value.
- */
- def qualityFactorBounds: BoundsWithDefault[Double]
-
- /**
- * initialDelay Specifies how much delay we should have before the quality factor calculation start to kick in. This is
- * mostly to ease the load during the initial warmup/startup.
- */
- def initialDelay: Duration
-
- /**
- * [[Throwable]]s that should be ignored when calculating
- * the [[QualityFactor]] if this is [[PartialFunction.isDefinedAt]]
- */
- def ignorableFailures: PartialFunction[Throwable, Unit] = defaultIgnorableFailures
-}
-
-object QualityFactorConfig {
-
- /**
- * Default value for [[QualityFactorConfig.ignorableFailures]] that ignores any
- * Cancelled requests and [[ClientFailure]]
- */
- val defaultIgnorableFailures: PartialFunction[Throwable, Unit] = {
- case PipelineFailure(_: ClientFailure, _, _, _) => ()
- case CancelledExceptionExtractor(_) => ()
- }
-}
-
-/**
- * This is a linear quality factor implementation, aimed to achieve and maintain a percentile latency target.
- *
- * If we call quality factor q, target latency t and target percentile p,
- * then the q (quality factor) formula should be:
- * q += delta for each request with latency <= t
- * q -= delta * p / (100 - p) for each request with latency > t ms or a timeout.
- *
- * When percentile p latency stays at target latency t, then based on the formula above, q will
- * stay constant (fluctuates around a constant value).
- *
- * For example, assume t = 100ms, p = p99, and q = 0.5
- * let's say, p99 latency stays at 100ms when q = 0.5. p99 means that out of every 100 latencies,
- * 99 times the latency is below 100ms and 1 time it is above 100ms. So based on the formula above,
- * q will increase by "delta" 99 times and it will decrease by delta * p / (100 - p) = delta * 99 once,
- * which results in the same q = 0.5.
- *
- * @param targetLatency This is the latency target, calls with latencies above which will cause quality
- * factor to go down, and vice versa. e.g. 500ms.
- * @param targetLatencyPercentile This the percentile where the target latency is aimed at. e.g. 95.0.
- * @param delta the step for adjusting quality factor. It should be a positive double. If delta is
- * too large, then quality factor will fluctuate more, and if it is too small, the
- * responsiveness will be reduced.
- */
-case class LinearLatencyQualityFactorConfig(
- override val qualityFactorBounds: BoundsWithDefault[Double],
- override val initialDelay: Duration,
- targetLatency: Duration,
- targetLatencyPercentile: Double,
- delta: Double,
- override val ignorableFailures: PartialFunction[Throwable, Unit] =
- QualityFactorConfig.defaultIgnorableFailures)
- extends QualityFactorConfig {
- require(
- targetLatencyPercentile >= 50.0 && targetLatencyPercentile < 100.0,
- s"Invalid targetLatencyPercentile value: ${targetLatencyPercentile}.\n" +
- s"Correct sample values: 95.0, 99.9. Incorrect sample values: 0.95, 0.999."
- )
-}
-
-/**
- * A quality factor provides component capacity state based on sampling component
- * Queries Per Second (qps) at local host level.
- *
- * If we call quality factor q, max qps R:
- * then the q (quality factor) formula should be:
- * q = Math.min([[qualityFactorBounds.bounds.maxInclusive]], q + delta) for each request that observed qps <= R on local host
- * q -= delta for each request that observed qps > R on local host
- *
- * When qps r stays below R, q will stay as constant (value at [[qualityFactorBounds.bounds.maxInclusive]]).
- * When qps r starts to increase above R, q will decrease by delta per request,
- * with delta being an additive factor that controls how sensitive q is when max qps R is exceeded.
- *
- * @param initialDelay Specifies an initial delay time to allow query rate counter warm up to start reflecting actual traffic load.
- * Qf value would only start to update after this initial delay.
- * @param maxQueriesPerSecond The max qps the underlying component can take. Requests go above this qps threshold will cause quality factor to go down.
- * @param queriesPerSecondSampleWindow The window of underlying query rate counter counting with and calculate an average qps over the window,
- * default to count with 10 seconds time window (i.e. qps = total requests over last 10 secs / 10).
- * Note: underlying query rate counter has a sliding window with 10 fixed slices. Therefore a larger
- * window would lead to a coarser qps calculation. (e.g. with 60 secs time window, it sliding over 6 seconds slice (60 / 10 = 6 secs)).
- * A larger time window also lead to a slower reaction to sudden qps burst, but more robust to flaky qps pattern.
- * @param delta The step for adjusting quality factor. It should be a positive double. If the delta is large, the quality factor
- * will fluctuate more and be more responsive to exceeding max qps, and if it is small, the quality factor will be less responsive.
- */
-case class QueriesPerSecondBasedQualityFactorConfig(
- override val qualityFactorBounds: BoundsWithDefault[Double],
- override val initialDelay: Duration,
- maxQueriesPerSecond: Int,
- queriesPerSecondSampleWindow: Duration = 10.seconds,
- delta: Double = 0.001,
- override val ignorableFailures: PartialFunction[Throwable, Unit] =
- QualityFactorConfig.defaultIgnorableFailures)
- extends QualityFactorConfig
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala
deleted file mode 100644
index e15fb5491..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.util.Duration
-import com.twitter.util.Try
-
-/** Updates the [[QualityFactor]] */
-trait QualityFactorObserver {
-
- /** The [[QualityFactor]] to update when observing */
- def qualityFactor: QualityFactor[_]
-
- /**
- * updates the [[qualityFactor]] given the result [[Try]] and the latency
- * @note implementations must be sure to correctly ignore
- * [[QualityFactor.config]]'s [[QualityFactorConfig.ignorableFailures]]
- */
- def apply(result: Try[_], latency: Duration): Unit
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala
deleted file mode 100644
index 01a327f86..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredQualityFactor
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-
-case class QualityFactorStatus(
- qualityFactorByPipeline: Map[ComponentIdentifier, QualityFactor[_]]) {
-
- /**
- * returns a new [[QualityFactorStatus]] with all the elements of current QualityFactorStatus and `other`.
- * If a [[ComponentIdentifier]] exists in both maps, the Value from `other` takes precedence
- */
- def ++(other: QualityFactorStatus): QualityFactorStatus = {
- if (other.qualityFactorByPipeline.isEmpty) {
- this
- } else if (qualityFactorByPipeline.isEmpty) {
- other
- } else {
- QualityFactorStatus(qualityFactorByPipeline ++ other.qualityFactorByPipeline)
- }
- }
-}
-
-object QualityFactorStatus {
- def build[Identifier <: ComponentIdentifier](
- qualityFactorConfigs: Map[Identifier, QualityFactorConfig]
- ): QualityFactorStatus = {
- QualityFactorStatus(
- qualityFactorConfigs.map {
- case (key, config: LinearLatencyQualityFactorConfig) =>
- key -> LinearLatencyQualityFactor(config)
- case (key, config: QueriesPerSecondBasedQualityFactorConfig) =>
- key -> QueriesPerSecondBasedQualityFactor(config)
- }
- )
- }
-
- val empty: QualityFactorStatus = QualityFactorStatus(Map.empty)
-}
-
-trait HasQualityFactorStatus {
- def qualityFactorStatus: Option[QualityFactorStatus] = None
- def withQualityFactorStatus(qualityFactorStatus: QualityFactorStatus): PipelineQuery
-
- def getQualityFactorCurrentValue(
- identifier: ComponentIdentifier
- ): Double = getQualityFactor(identifier).currentValue
-
- def getQualityFactor(
- identifier: ComponentIdentifier
- ): QualityFactor[_] = qualityFactorStatus
- .flatMap(_.qualityFactorByPipeline.get(identifier))
- .getOrElse {
- throw PipelineFailure(
- MisconfiguredQualityFactor,
- s"Quality factor not configured for $identifier")
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala
deleted file mode 100644
index a1ba3f373..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.google.common.annotations.VisibleForTesting
-import com.twitter.util.Stopwatch
-
-case class QueriesPerSecondBasedQualityFactor(
- override val config: QueriesPerSecondBasedQualityFactorConfig)
- extends QualityFactor[Int] {
-
- @VisibleForTesting
- private[quality_factor] val queryRateCounter: QueryRateCounter = QueryRateCounter(
- config.queriesPerSecondSampleWindow)
-
- private val delayedUntilInMillis = Stopwatch.timeMillis() + config.initialDelay.inMillis
-
- private var state: Double = config.qualityFactorBounds.default
-
- override def currentValue: Double = state
-
- override def update(count: Int = 1): Unit = {
- val queryRate = incrementAndGetQueryRateCount(count)
-
- // Only update quality factor until the initial delay past.
- // This allows query rate counter get warm up to reflect
- // actual traffic load by the time initial delay expires.
- if (Stopwatch.timeMillis() >= delayedUntilInMillis) {
- if (queryRate > config.maxQueriesPerSecond) {
- state = config.qualityFactorBounds.bounds(state - config.delta)
- } else {
- state = config.qualityFactorBounds.bounds(state + config.delta)
- }
- }
- }
-
- private def incrementAndGetQueryRateCount(count: Int): Double = {
- // Int.MaxValue is used as a special signal from [[QueriesPerSecondBasedQualityFactorObserver]]
- // to indicate a component failure is observed.
- // In this case, we do not update queryRateCounter and instead return Int.MaxValue.
- // As the largest Int value, this should result in the threshold qps for quality factor being
- // exceeded and directly decrementing quality factor.
- if (count == Int.MaxValue) {
- Int.MaxValue.toDouble
- } else {
- queryRateCounter.increment(count)
- queryRateCounter.getRate()
- }
- }
-
- override def buildObserver(): QualityFactorObserver =
- QueriesPerSecondBasedQualityFactorObserver(this)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala
deleted file mode 100644
index 27f13c8a3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.util.Duration
-import com.twitter.util.Try
-
-case class QueriesPerSecondBasedQualityFactorObserver(
- override val qualityFactor: QueriesPerSecondBasedQualityFactor)
- extends QualityFactorObserver {
- override def apply(
- result: Try[_],
- latency: Duration
- ): Unit = {
- result
- .onSuccess(_ => qualityFactor.update())
- .onFailure {
- case t if qualityFactor.config.ignorableFailures.isDefinedAt(t) => ()
- // Degrade qf as a proactive mitigation for any non ignorable failures.
- case _ => qualityFactor.update(Int.MaxValue)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala
deleted file mode 100644
index 33d4a5375..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.twitter.product_mixer.core.quality_factor
-
-import com.twitter.util.Duration
-import com.twitter.util.Stopwatch
-import com.twitter.util.TokenBucket
-
-/**
- * Query rate counter based on a leaky bucket. For more, see [[com.twitter.util.TokenBucket]].
- */
-case class QueryRateCounter private[quality_factor] (
- queryRateWindow: Duration) {
-
- private val queryRateWindowInSeconds = queryRateWindow.inSeconds
-
- private val leakyBucket: TokenBucket =
- TokenBucket.newLeakyBucket(ttl = queryRateWindow, reserve = 0, nowMs = Stopwatch.timeMillis)
-
- def increment(count: Int): Unit = leakyBucket.put(count)
-
- def getRate(): Double = leakyBucket.count / queryRateWindowInSeconds
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD
deleted file mode 100644
index 72565730e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer",
- "servo/util",
- "stitch/stitch-core",
- "util/util-core",
- "util/util-stats",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer",
- "stitch/stitch-core",
- "util/util-stats",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala
deleted file mode 100644
index d56c1e0fc..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala
+++ /dev/null
@@ -1,700 +0,0 @@
-package com.twitter.product_mixer.core.service
-
-import com.twitter.finagle.stats.BroadcastStatsReceiver
-import com.twitter.finagle.stats.Counter
-import com.twitter.finagle.stats.DefaultStatsReceiver
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finagle.tracing.Annotation
-import com.twitter.finagle.tracing.Record
-import com.twitter.finagle.tracing.Trace
-import com.twitter.finagle.tracing.TraceId
-import com.twitter.finagle.tracing.TraceServiceName
-import com.twitter.finagle.tracing.Tracing.LocalBeginAnnotation
-import com.twitter.finagle.tracing.Tracing.LocalEndAnnotation
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UncategorizedServerFailure
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.service.Executor.AlwaysFailOpenIncludingProgrammerErrors
-import com.twitter.product_mixer.core.service.Executor.Context
-import com.twitter.product_mixer.core.service.Executor.TracingConfig
-import com.twitter.product_mixer.core.service.Executor.toPipelineFailureWithComponentIdentifierStack
-import com.twitter.servo.util.CancelledExceptionExtractor
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import com.twitter.stitch.Stitch.Letter
-import com.twitter.util.Duration
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Time
-import com.twitter.util.Try
-
-/**
- * Base trait that all executors implement
- *
- * All executors should:
- * - implement a `def arrow` or `def apply` with the relevant types for their use case
- * and take in an implicit [[PipelineFailureClassifier]] and [[ComponentIdentifierStack]].
- * - add a `@singleton` annotation to the class and `@inject` annotation to the argument list
- * - take in a [[StatsReceiver]]
- *
- * @example {{{
- * @Singleton class MyExecutor @Inject() (
- * override val statsReceiver: StatsReceiver
- * ) extends Executor {
- * def arrow(
- * arg: MyArg,
- * ...,
- * context: Context
- * ): Arrow[In,Out] = ???
- * }
- * }}}
- */
-private[core] trait Executor {
- val statsReceiver: StatsReceiver
-
- /**
- * Applies the `pipelineFailureClassifier` to the output of the `arrow`
- * and adds the `componentStack` to the [[PipelineFailure]]
- */
- def wrapWithErrorHandling[In, Out](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- arrow.mapFailure(
- toPipelineFailureWithComponentIdentifierStack(context, currentComponentIdentifier))
- }
-
- /**
- * Chain a `Seq` of [[Arrow.Iso]], only passing successful results to the next [[Arrow.Iso]]
- *
- * @note the resulting [[Arrow]] runs the passed in [[Arrow]]s one after the other,
- * as an ordered execution, this means that each [[Arrow]] is dependent
- * on all previous [[Arrow]]s in the `Seq` so no `Stitch` batching can occur
- * between them.
- */
- def isoArrowsSequentially[T](arrows: Seq[Arrow.Iso[T]]): Arrow.Iso[T] = {
- // avoid excess Arrow complexity when there is only a single Arrow
- arrows match {
- case Seq() => Arrow.identity
- case Seq(onlyOneArrow) => onlyOneArrow
- case Seq(head, tail @ _*) =>
- tail.foldLeft(head) {
- case (combinedArrow, nextArrow) => combinedArrow.flatMapArrow(nextArrow)
- }
- }
- }
-
- /**
- * Start running the [[Arrow]] in the background returning a [[Stitch.Ref]] which will complete
- * when the background task is finished
- */
- def startArrowAsync[In, Out](arrow: Arrow[In, Out]): Arrow[In, Stitch[Out]] = {
- Arrow
- .map { arg: In =>
- // wrap in a `ref` so we only compute it's value once
- Stitch.ref(arrow(arg))
- }
- .andThen(
- Arrow.zipWithArg(
- // satisfy the `ref` async
- Arrow.async(Arrow.flatMap[Stitch[Out], Out](identity))))
- .map { case (ref, _) => ref }
- }
-
- /**
- * for [[com.twitter.product_mixer.core.model.common.Component]]s which
- * are executed per-candidate or which we don't want to record stats for.
- * This performs Tracing but does not record Stats
- *
- * @note This should be used around the computation that includes the execution of the
- * underlying Component over all the Candidates, not around each execution
- * of the component around each candidate for per-candidate Components.
- *
- * @note when using this you should only use [[wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing]]
- * for handling Stats.
- */
- def wrapComponentsWithTracingOnly[In, Out](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- Executor.wrapArrowWithLocalTracingSpan(
- Arrow
- .time(arrow)
- .map {
- case (result, latency) =>
- Executor.recordTraceData(
- componentStack = context.componentStack,
- componentIdentifier = currentComponentIdentifier,
- result = result,
- latency = latency,
- size = None)
- result
- }.lowerFromTry)
- }
-
- /**
- * for [[com.twitter.product_mixer.core.model.common.Component]]s which
- * are executed per-candidate. Records Stats but does not do Tracing.
- *
- * @note when using this you should only use [[wrapPerCandidateComponentsWithTracingOnly]]
- * for handling Tracing
- */
- def wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing[In, Out](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Out](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = Return(_),
- tracingConfig = TracingConfig.NoTracing
- )(arrow)
- }
-
- /** for [[com.twitter.product_mixer.core.model.common.Component]]s */
- def wrapComponentWithExecutorBookkeeping[In, Out](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Out](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = Return(_)
- )(arrow)
- }
-
- /**
- * for [[com.twitter.product_mixer.core.model.common.Component]]s which an `onSuccess`
- * to add custom stats or logging of results
- */
- def wrapComponentWithExecutorBookkeeping[In, Out](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- onSuccess: Out => Unit
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Out](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = Return(_),
- onComplete = (transformed: Try[Out]) => transformed.onSuccess(onSuccess)
- )(arrow)
- }
-
- /** for [[com.twitter.product_mixer.core.pipeline.Pipeline]]s */
- def wrapPipelineWithExecutorBookkeeping[In, Out <: PipelineResult[_]](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- qualityFactorObserver: Option[QualityFactorObserver],
- failOpenPolicy: FailOpenPolicy = FailOpenPolicy.Never
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver
- .pipelineExecutorObserver[Out](context, currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Out](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = (result: Out) => result.toTry,
- size = Some(_.resultSize()),
- failOpenPolicy = failOpenPolicy,
- qualityFactorObserver = qualityFactorObserver
- )(arrow)
- }
-
- /** for [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]]s */
- def wrapProductPipelineWithExecutorBookkeeping[In, Out <: PipelineResult[_]](
- context: Context,
- currentComponentIdentifier: ProductPipelineIdentifier
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
-
- val observerSideEffect =
- ExecutorObserver
- .productPipelineExecutorObserver[Out](currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Out](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = _.toTry,
- size = Some(_.resultSize()),
- failOpenPolicy =
- // always save Failures in the Result object instead of failing the request
- AlwaysFailOpenIncludingProgrammerErrors
- )(arrow)
- }
-
- /** for [[com.twitter.product_mixer.core.model.common.Component]]s which need a result size stat */
- def wrapComponentWithExecutorBookkeepingWithSize[In, Out](
- context: Context,
- currentComponentIdentifier: CandidateSourceIdentifier,
- size: Out => Int
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver.executorObserverWithSize(context, currentComponentIdentifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Int](
- context = context,
- currentComponentIdentifier = currentComponentIdentifier,
- executorResultSideEffect = observerSideEffect,
- transformer = (out: Out) => Try(size(out)),
- size = Some(identity)
- )(arrow)
- }
-
- /** for [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step]]s */
- def wrapStepWithExecutorBookkeeping[In, Out](
- context: Context,
- identifier: PipelineStepIdentifier,
- arrow: Arrow[In, Out],
- transformer: Out => Try[Unit]
- ): Arrow[In, Out] = {
- val observerSideEffect =
- ExecutorObserver.stepExecutorObserver(context, identifier, statsReceiver)
-
- Executor.wrapWithExecutorBookkeeping[In, Out, Unit](
- context = context,
- currentComponentIdentifier = identifier,
- executorResultSideEffect = observerSideEffect,
- transformer = transformer,
- failOpenPolicy = AlwaysFailOpenIncludingProgrammerErrors
- )(arrow)
- }
-}
-
-private[core] object Executor {
-
- private[service] object TracingConfig {
-
- /** Used to specify whether a wrapped Arrow should be Traced in [[wrapWithExecutorBookkeeping]] */
- sealed trait TracingConfig
- case object NoTracing extends TracingConfig
- case object WrapWithSpanAndTracingData extends TracingConfig
- }
-
- /**
- * Always fail-open and return the [[com.twitter.product_mixer.core.pipeline.product.ProductPipelineResult]]
- * containing the exception, this differs from [[FailOpenPolicy.Always]] in that this will still
- * fail-open and return the overall result object even if the underlying failure is the result
- * of programmer error.
- */
- private val AlwaysFailOpenIncludingProgrammerErrors: FailOpenPolicy = _ => true
-
- /**
- * Wraps an [[Arrow]] so that bookkeeping around the execution occurs uniformly.
- *
- * @note should __never__ be called directly!
- *
- * - For successful results, apply the `transformer`
- * - convert any exceptions to PipelineFailures
- * - record stats and update [[QualityFactorObserver]]
- * - wraps the execution in a Trace span and record Trace data (can be turned off by [[TracingConfig]])
- * - applies a trace span and records metadata to the provided `arrow`
- * - determine whether to fail-open based on `result.flatMap(transformer)`
- * - if failing-open, always return the original result
- * - if failing-closed and successful, return the original result
- * - otherwise, return the failure (from `result.flatMap(transformer)`)
- *
- * @param context the [[Executor.Context]]
- * @param currentComponentIdentifier the current component's [[ComponentIdentifier]]
- * @param executorResultSideEffect the [[ExecutorObserver]] used to record stats
- * @param transformer function to convert a successful result into possibly a failed result
- * @param failOpenPolicy [[FailOpenPolicy]] to apply to the results of `result.flatMap(transformer)`
- * @param qualityFactorObserver [[QualityFactorObserver]] to update based on the results of `result.flatMap(transformer)`
- * @param tracingConfig indicates whether the [[Arrow]] should be wrapped with Tracing
- * @param onComplete runs the function for its side effects with the result of `result.flatMap(transformer)`
- * @param arrow an input [[Arrow]] to wrap so that after it's execution, we perform all these operations
- *
- * @return the wrapped [[Arrow]]
- */
- private[service] def wrapWithExecutorBookkeeping[In, Out, Transformed](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- executorResultSideEffect: ExecutorObserver[Transformed],
- transformer: Out => Try[Transformed],
- size: Option[Transformed => Int] = None,
- failOpenPolicy: FailOpenPolicy = FailOpenPolicy.Never,
- qualityFactorObserver: Option[QualityFactorObserver] = None,
- tracingConfig: TracingConfig.TracingConfig = TracingConfig.WrapWithSpanAndTracingData,
- onComplete: Try[Transformed] => Unit = { _: Try[Transformed] => () }
- )(
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] = {
-
- val failureClassifier =
- toPipelineFailureWithComponentIdentifierStack(context, currentComponentIdentifier)
-
- /** transform the results, mapping all exceptions to [[PipelineFailure]]s, and tuple with original result */
- val transformResultAndClassifyFailures: Arrow[Out, (Out, Try[Transformed])] =
- Arrow.join(
- Arrow.mapFailure(failureClassifier),
- Arrow
- .transformTry[Out, Transformed](result =>
- result
- .flatMap(transformer)
- .rescue { case t => Throw(failureClassifier(t)) })
- .liftToTry
- )
-
- /** Only record tracing data if [[TracingConfig.WrapWithSpanAndTracingData]] */
- val maybeRecordTracingData: (Try[Transformed], Duration) => Unit = tracingConfig match {
- case TracingConfig.NoTracing => (_, _) => ()
- case TracingConfig.WrapWithSpanAndTracingData =>
- (transformedAndClassifiedResult, latency) =>
- recordTraceData(
- context.componentStack,
- currentComponentIdentifier,
- transformedAndClassifiedResult,
- latency,
- transformedAndClassifiedResult.toOption.flatMap(result => size.map(_.apply(result)))
- )
- }
-
- /** Will never be in a failed state so we can do a simple [[Arrow.map]] */
- val recordStatsAndUpdateQualityFactor =
- Arrow
- .map[(Try[(Out, Try[Transformed])], Duration), Unit] {
- case (tryResultAndTryTransformed, latency) =>
- val transformedAndClassifiedResult = tryResultAndTryTransformed.flatMap {
- case (_, transformed) => transformed
- }
- executorResultSideEffect(transformedAndClassifiedResult, latency)
- qualityFactorObserver.foreach(_.apply(transformedAndClassifiedResult, latency))
- onComplete(transformedAndClassifiedResult)
- maybeRecordTracingData(transformedAndClassifiedResult, latency)
- }.unit
-
- /**
- * Applies the provided [[FailOpenPolicy]] based on the [[transformer]]'s results,
- * returning the original result or an exception
- */
- val applyFailOpenPolicyBasedOnTransformedResult: Arrow[
- (Try[(Out, Try[Transformed])], Duration),
- Out
- ] =
- Arrow
- .map[(Try[(Out, Try[Transformed])], Duration), Try[(Out, Try[Transformed])]] {
- case (tryResultAndTryTransformed, _) => tryResultAndTryTransformed
- }
- .lowerFromTry
- .map {
- case (result, Throw(pipelineFailure: PipelineFailure))
- if failOpenPolicy(pipelineFailure.category) =>
- Return(result)
- case (_, t: Throw[_]) => t.asInstanceOf[Throw[Out]]
- case (result, _) => Return(result)
- }.lowerFromTry
-
- /** The complete Arrow minus a Local span wrapping */
- val arrowWithTimingExecutorSideEffects = Arrow
- .time(arrow.andThen(transformResultAndClassifyFailures))
- .applyEffect(recordStatsAndUpdateQualityFactor)
- .andThen(applyFailOpenPolicyBasedOnTransformedResult)
-
- /** Dont wrap with a span if we are not tracing */
- tracingConfig match {
- case TracingConfig.WrapWithSpanAndTracingData =>
- wrapArrowWithLocalTracingSpan(arrowWithTimingExecutorSideEffects)
- case TracingConfig.NoTracing =>
- arrowWithTimingExecutorSideEffects
- }
- }
-
- /** Let-scopes a [[TraceId]] around a computation */
- private[this] object TracingLetter extends Letter[TraceId] {
- override def let[S](traceId: TraceId)(s: => S): S = Trace.letId(traceId)(s)
- }
-
- /**
- * Wraps the Arrow's execution in a new trace span as a child of the current parent span
- *
- * @note Should __never__ be called directly!
- *
- * It's expected that the contained `arrow` will invoke [[recordTraceData]] exactly ONCE
- * during it's execution.
- *
- * @note this does not record any data about the trace, it only sets the [[Trace]] Span
- * for the execution of `arrow`
- */
- private[service] def wrapArrowWithLocalTracingSpan[In, Out](
- arrow: Arrow[In, Out]
- ): Arrow[In, Out] =
- Arrow.ifelse(
- _ => Trace.isActivelyTracing,
- Arrow.let(TracingLetter)(Trace.nextId)(arrow),
- arrow
- )
-
- private[this] object Tracing {
-
- /**
- * Duplicate of [[com.twitter.finagle.tracing.Tracing]]'s `localSpans` which
- * uses an un-scoped [[StatsReceiver]]
- *
- * Since we needed to roll-our-own latency measurement we are unable to increment the
- * `local_spans` metric automatically, this is important in the event a service is
- * unexpectedly not recording spans or unexpectedly recording too many, so we manually
- * increment it
- */
- val localSpans: Counter = DefaultStatsReceiver.counter("tracing", "local_spans")
-
- /** Local Component field of a span in the UI */
- val localComponentTag = "lc"
- val sizeTag = "product_mixer.result.size"
- val successTag = "product_mixer.result.success"
- val successValue = "success"
- val cancelledTag = "product_mixer.result.cancelled"
- val failureTag = "product_mixer.result.failure"
- }
-
- /**
- * Records metadata onto the current [[Trace]] Span
- *
- * @note Should __never__ be called directly!
- *
- * This should be called exactly ONCE in the Arrow passed into [[wrapArrowWithLocalTracingSpan]]
- * to record data for the Span.
- */
- private[service] def recordTraceData[T](
- componentStack: ComponentIdentifierStack,
- componentIdentifier: ComponentIdentifier,
- result: Try[T],
- latency: Duration,
- size: Option[Int] = None
- ): Unit = {
- if (Trace.isActivelyTracing) {
- Tracing.localSpans.incr()
- val traceId = Trace.id
- val endTime = Time.nowNanoPrecision
-
- // These annotations are needed for the Zipkin UI to display the span properly
- TraceServiceName().foreach(Trace.recordServiceName)
- Trace.recordRpc(componentIdentifier.snakeCase) // name of the span in the UI
- Trace.recordBinary(
- Tracing.localComponentTag,
- componentStack.peek.toString + "/" + componentIdentifier.toString)
- Trace.record(Record(traceId, endTime - latency, Annotation.Message(LocalBeginAnnotation)))
- Trace.record(Record(traceId, endTime, Annotation.Message(LocalEndAnnotation)))
-
- // product mixer specific zipkin data
- size.foreach(size => Trace.recordBinary(Tracing.sizeTag, size))
- result match {
- case Return(_) =>
- Trace.recordBinary(Tracing.successTag, Tracing.successValue)
- case Throw(CancelledExceptionExtractor(e)) =>
- Trace.recordBinary(Tracing.cancelledTag, e)
- case Throw(e) =>
- Trace.recordBinary(Tracing.failureTag, e)
- }
- }
- }
-
- /**
- * Returns a tuple of the stats scopes for the current component and the relative scope for
- * the parent component and the current component together
- *
- * This is useful when recording stats for a component by itself as well as stats for calls to that component from it's parent.
- *
- * @example if the current component has a scope of "currentComponent" and the parent component has a scope of "parentComponent"
- * then this will return `(Seq("currentComponent"), Seq("parentComponent", "currentComponent"))`
- */
- def buildScopes(
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- ): Executor.Scopes = {
- val parentScopes = context.componentStack.peek.toScopes
- val componentScopes = currentComponentIdentifier.toScopes
- val relativeScopes = parentScopes ++ componentScopes
- Executor.Scopes(componentScopes, relativeScopes)
- }
-
- /**
- * Makes a [[BroadcastStatsReceiver]] that will broadcast stats to the correct
- * current component's scope and to the scope relative to the parent.
- */
- def broadcastStatsReceiver(
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- statsReceiver: StatsReceiver
- ): StatsReceiver = {
- val Executor.Scopes(componentScopes, relativeScopes) =
- Executor.buildScopes(context, currentComponentIdentifier)
-
- BroadcastStatsReceiver(
- Seq(statsReceiver.scope(relativeScopes: _*), statsReceiver.scope(componentScopes: _*)))
- }
-
- /**
- * Returns a feature map containing all the [[com.twitter.product_mixer.core.feature.Feature]]s
- * stored as failures using the exception provided with as the reason wrapped in a PipelineFailure.
- * e.g, for features A & B that threw an ExampleException b, this will return:
- * { A -> Throw(PipelineFailure(...)), B -> Throw(PipelineFailure(...)) }
- */
- def featureMapWithFailuresForFeatures(
- features: Set[Feature[_, _]],
- error: Throwable,
- context: Executor.Context
- ): FeatureMap = {
- val builder = FeatureMapBuilder()
- features.foreach { feature =>
- val pipelineFailure = PipelineFailure(
- FeatureHydrationFailed,
- s"Feature hydration failed for ${feature.toString}",
- Some(error),
- Some(context.componentStack))
- builder.addFailure(feature, pipelineFailure)
- }
- builder.build()
- }
-
- /**
- * Validates and returns back the passed feature map if it passes validation. A feature map
- * is considered valid if it contains only the passed `registeredFeatures` features in it,
- * nothing else and nothing missing.
- */
- @throws(classOf[PipelineFailure])
- def validateFeatureMap(
- registeredFeatures: Set[Feature[_, _]],
- featureMap: FeatureMap,
- context: Executor.Context
- ): FeatureMap = {
- val hydratedFeatures = featureMap.getFeatures
- if (hydratedFeatures == registeredFeatures) {
- featureMap
- } else {
- val missingFeatures = registeredFeatures -- hydratedFeatures
- val unregisteredFeatures = hydratedFeatures -- registeredFeatures
- throw PipelineFailure(
- MisconfiguredFeatureMapFailure,
- s"Unregistered features $unregisteredFeatures and missing features $missingFeatures",
- None,
- Some(context.componentStack)
- )
- }
- }
-
- object NotAMisconfiguredFeatureMapFailure {
-
- /**
- * Will return any exception that isn't a [[MisconfiguredFeatureMapFailure]] [[PipelineFailure]]
- * Allows for easy [[Arrow.handle]]ing all exceptions that aren't [[MisconfiguredFeatureMapFailure]]s
- */
- def unapply(e: Throwable): Option[Throwable] = e match {
- case pipelineFailure: PipelineFailure
- if pipelineFailure.category == MisconfiguredFeatureMapFailure =>
- None
- case e => Some(e)
- }
- }
-
- /**
- * contains the scopes for recording metrics for the component by itself and
- * the relative scope of that component within it's parent component scope
- *
- * @see [[Executor.buildScopes]]
- */
- case class Scopes(componentScopes: Seq[String], relativeScope: Seq[String])
-
- /**
- * Wrap the [[Throwable]] in a [[UncategorizedServerFailure]] [[PipelineFailure]] with the original
- * [[Throwable]] as the cause, even if it's already a [[PipelineFailure]].
- *
- * This ensures that any access to the stored feature will result in a meaningful [[UncategorizedServerFailure]]
- * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory]] in stats which is more useful
- * for customers components which access a failed [[Feature]] than the original [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory]].
- */
- def uncategorizedServerFailure(
- componentStack: ComponentIdentifierStack,
- throwable: Throwable
- ): PipelineFailure = {
- PipelineFailure(
- UncategorizedServerFailure,
- reason = "Unclassified Failure in Pipeline",
- Some(throwable),
- Some(componentStack)
- )
- }
-
- /**
- * [[PartialFunction]] that converts any [[Throwable]] into a
- * [[PipelineFailure]] based on the provided `failureClassifier`
- */
- def toPipelineFailureWithComponentIdentifierStack(
- context: Context,
- currentComponentIdentifier: ComponentIdentifier
- ): PipelineFailureClassifier = {
- // if given a `currentComponentIdentifier` then ensure we correctly handle `BasedOnParentComponent` identifier types
- val contextWithCurrentComponentIdentifier =
- context.pushToComponentStack(currentComponentIdentifier)
- PipelineFailureClassifier(
- contextWithCurrentComponentIdentifier.pipelineFailureClassifier
- .orElse[Throwable, PipelineFailure] {
- case CancelledExceptionExtractor(throwable) => throw throwable
- case pipelineFailure: PipelineFailure => pipelineFailure
- case throwable =>
- uncategorizedServerFailure(
- contextWithCurrentComponentIdentifier.componentStack,
- throwable)
- }.andThen { pipelineFailure =>
- pipelineFailure.componentStack match {
- case _: Some[_] => pipelineFailure
- case None =>
- pipelineFailure.copy(componentStack =
- Some(contextWithCurrentComponentIdentifier.componentStack))
- }
- }
- )
- }
-
- /**
- * information used by an [[Executor]] that provides context around execution
- */
- case class Context(
- pipelineFailureClassifier: PipelineFailureClassifier,
- componentStack: ComponentIdentifierStack) {
-
- def pushToComponentStack(newComponentIdentifier: ComponentIdentifier): Context =
- copy(componentStack = componentStack.push(newComponentIdentifier))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala
deleted file mode 100644
index 16df331fb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala
+++ /dev/null
@@ -1,146 +0,0 @@
-package com.twitter.product_mixer.core.service
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.Executor.Context
-import com.twitter.product_mixer.shared_library.observer.Observer
-import com.twitter.product_mixer.shared_library.observer.Observer.Observer
-import com.twitter.product_mixer.shared_library.observer.ResultsStatsObserver.ResultsStatsObserver
-import com.twitter.util.Duration
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-
-private[core] object ExecutorObserver {
-
- /** Make a [[ExecutorObserver]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */
- def executorObserver[T](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- statsReceiver: StatsReceiver
- ): ExecutorObserver[T] = new ExecutorObserver[T](
- Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver))
-
- /** Make a [[ExecutorObserverWithSize]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */
- def executorObserverWithSize(
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- statsReceiver: StatsReceiver
- ): ExecutorObserverWithSize = new ExecutorObserverWithSize(
- Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver))
-
- /** Make a [[PipelineExecutorObserver]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */
- def pipelineExecutorObserver[T <: PipelineResult[_]](
- context: Context,
- currentComponentIdentifier: ComponentIdentifier,
- statsReceiver: StatsReceiver
- ): PipelineExecutorObserver[T] = new PipelineExecutorObserver[T](
- Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver))
-
- /**
- * Make a [[PipelineExecutorObserver]] specifically for a [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]]
- * with no relative stats
- */
- def productPipelineExecutorObserver[T <: PipelineResult[_]](
- currentComponentIdentifier: ProductPipelineIdentifier,
- statsReceiver: StatsReceiver
- ): PipelineExecutorObserver[T] =
- new PipelineExecutorObserver[T](statsReceiver.scope(currentComponentIdentifier.toScopes: _*))
-
- /**
- * Make a [[PipelineExecutorObserver]] with only stats relative to the parent pipeline
- * for [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step]]s
- */
- def stepExecutorObserver(
- context: Context,
- currentComponentIdentifier: PipelineStepIdentifier,
- statsReceiver: StatsReceiver
- ): ExecutorObserver[Unit] = {
- new ExecutorObserver[Unit](
- statsReceiver.scope(
- Executor.buildScopes(context, currentComponentIdentifier).relativeScope: _*))
- }
-}
-
-/**
- * An [[Observer]] which is called as a side effect. Unlike the other observers which wrap a computation,
- * this [[Observer]] expects the caller to provide the latency value and wire it in
- */
-private[core] sealed class ExecutorObserver[T](
- override val statsReceiver: StatsReceiver)
- extends {
-
- /**
- * always empty because we expect an already scoped [[com.twitter.finagle.stats.BroadcastStatsReceiver]] to be passed in
- * @note uses early definitions [[https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html]] to avoid null values for `scopes` in [[Observer]]
- */
- override val scopes: Seq[String] = Seq.empty
-} with Observer[T] {
-
- /**
- * Serialize the provided [[Throwable]], prefixing [[PipelineFailure]]s with their
- * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory.categoryName]] and
- * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory.failureName]]
- */
- override def serializeThrowable(throwable: Throwable): Seq[String] = {
- throwable match {
- case PipelineFailure(category, _, None, _) =>
- Seq(category.categoryName, category.failureName)
- case PipelineFailure(category, _, Some(underlying), _) =>
- Seq(category.categoryName, category.failureName) ++ serializeThrowable(underlying)
- case throwable: Throwable => super.serializeThrowable(throwable)
- }
- }
-
- /** record success, failure, and latency stats based on `t` and `latency` */
- def apply(t: Try[T], latency: Duration): Unit = observe(t, latency)
-}
-
-/**
- * Same as [[ExecutorObserver]] but records a size stat for [[PipelineResult]]s and
- * records a failure counter for the cause of the failure under `failures/$pipelineFailureCategory/$componentType/$componentName`.
- *
- * @example if `GateIdentifier("MyGate")` is at the top of the [[PipelineFailure.componentStack]] then
- * the resulting metric `failures/ClientFailure/Gate/MyGate` will be incremented.
- */
-private[core] final class PipelineExecutorObserver[T <: PipelineResult[_]](
- override val statsReceiver: StatsReceiver)
- extends ExecutorObserver[T](statsReceiver)
- with ResultsStatsObserver[T] {
- override val size: T => Int = _.resultSize()
-
- override def apply(t: Try[T], latency: Duration): Unit = {
- super.apply(t, latency)
- t match {
- case Return(result) => observeResults(result)
- case Throw(PipelineFailure(category, _, _, Some(componentIdentifierStack))) =>
- statsReceiver
- .counter(
- Seq(
- Observer.Failures,
- category.categoryName,
- category.failureName) ++ componentIdentifierStack.peek.toScopes: _*).incr()
- case _ =>
- }
- }
-}
-
-/** Same as [[ExecutorObserver]] but records a size stat */
-private[core] final class ExecutorObserverWithSize(
- override val statsReceiver: StatsReceiver)
- extends ExecutorObserver[Int](statsReceiver)
- with ResultsStatsObserver[Int] {
- override val size: Int => Int = identity
-
- override def apply(t: Try[Int], latency: Duration): Unit = {
- super.apply(t, latency)
- t match {
- case Return(result) => observeResults(result)
- case _ =>
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala
deleted file mode 100644
index 3a37870bd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-package com.twitter.product_mixer.core.service
-
-trait ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala
deleted file mode 100644
index 799112be2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.twitter.product_mixer.core.service.async_feature_map_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor._
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class AsyncFeatureMapExecutor @Inject() (
- override val statsReceiver: StatsReceiver)
- extends Executor {
-
- /**
- * Forces an [[AsyncFeatureMap]] to hydrate and resolve into a [[FeatureMap]]
- * containing all [[com.twitter.product_mixer.core.feature.Feature]]s that are
- * supposed to be hydrated before `stepToHydrateBefore`.
- */
- def arrow(
- stepToHydrateFor: PipelineStepIdentifier,
- currentStep: PipelineStepIdentifier,
- context: Context
- ): Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = {
- Arrow
- .map[AsyncFeatureMap, Option[Stitch[FeatureMap]]](_.hydrate(stepToHydrateFor))
- .andThen(
- Arrow.choose(
- Arrow.Choice.ifDefinedAt(
- { case Some(stitchOfFeatureMap) => stitchOfFeatureMap },
- // only stat if there's something to hydrate
- wrapComponentWithExecutorBookkeeping(context, currentStep)(
- Arrow
- .flatMap[Stitch[FeatureMap], FeatureMap](identity)
- .map(featureMap =>
- AsyncFeatureMapExecutorResults(Map(stepToHydrateFor -> featureMap)))
- )
- ),
- Arrow.Choice.otherwise(Arrow.value(AsyncFeatureMapExecutorResults(Map.empty)))
- )
- )
- }
-}
-
-case class AsyncFeatureMapExecutorResults(
- featureMapsByStep: Map[PipelineStepIdentifier, FeatureMap])
- extends ExecutorResult {
- def ++(
- asyncFeatureMapExecutorResults: AsyncFeatureMapExecutorResults
- ): AsyncFeatureMapExecutorResults =
- AsyncFeatureMapExecutorResults(
- featureMapsByStep ++ asyncFeatureMapExecutorResults.featureMapsByStep)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD
deleted file mode 100644
index 7b70b50e6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD
deleted file mode 100644
index f1b84bbc7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala
deleted file mode 100644
index 141d9bce1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_decorator_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CandidateDecoratorExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
- def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- decoratorOpt: Option[CandidateDecorator[Query, Candidate]],
- context: Executor.Context
- ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] = {
- val decoratorArrow =
- decoratorOpt match {
- case Some(decorator) =>
- val candidateDecoratorArrow =
- Arrow.flatMap[(Query, Seq[CandidateWithFeatures[Candidate]]), Seq[Decoration]] {
- case (query, candidatesWithFeatures) => decorator.apply(query, candidatesWithFeatures)
- }
-
- wrapComponentWithExecutorBookkeeping(context, decorator.identifier)(
- candidateDecoratorArrow)
-
- case _ => Arrow.value(Seq.empty[Decoration])
- }
-
- decoratorArrow.map(CandidateDecoratorExecutorResult)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala
deleted file mode 100644
index 3f882c963..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_decorator_executor
-
-import com.twitter.product_mixer.core.functional_component.decorator.Decoration
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class CandidateDecoratorExecutorResult(result: Seq[Decoration]) extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD
deleted file mode 100644
index 8395e2754..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala
deleted file mode 100644
index f25e7bedf..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala
+++ /dev/null
@@ -1,277 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.HydratorCandidateResult
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor._
-import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor.Inputs
-import com.twitter.product_mixer.core.service.feature_hydrator_observer.FeatureHydratorObserver
-import com.twitter.stitch.Arrow
-import com.twitter.util.Try
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CandidateFeatureHydratorExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
- def arrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- hydrators: Seq[BaseCandidateFeatureHydrator[Query, Result, _]],
- context: Executor.Context
- ): Arrow[
- Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[
- Result
- ]
- ] = {
-
- val observer = new FeatureHydratorObserver(statsReceiver, hydrators, context)
-
- val candidateFeatureHydratorExecutorResults: Seq[Arrow[
- Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ]] = hydrators.map(getCandidateHydratorArrow(_, context, observer))
-
- val runHydrators = Arrow.collect(candidateFeatureHydratorExecutorResults).map {
- candidateFeatureHydratorExecutorResult: Seq[CandidateFeatureHydratorExecutorResult[Result]] =>
- candidateFeatureHydratorExecutorResult.foldLeft(
- CandidateFeatureHydratorExecutorResult[Result](
- Seq.empty,
- Map.empty
- )
- ) { (accumulator, additionalResult) =>
- // accumulator.results and additionalResults.results are either the same length or one may be empty
- // checks in each Hydrator's Arrow implementation ensure the ordering and length are correct
- val mergedFeatureMaps =
- if (accumulator.results.length == additionalResult.results.length) {
- // merge if there are results for both and they are the same size
- // also handles both being empty
- accumulator.results.zip(additionalResult.results).map {
- case (accumulatedScoredCandidate, resultScoredCandidate) =>
- val updatedFeatureMap =
- accumulatedScoredCandidate.features ++ resultScoredCandidate.features
- HydratorCandidateResult(resultScoredCandidate.candidate, updatedFeatureMap)
- }
- } else if (accumulator.results.isEmpty) {
- // accumulator is empty (the initial case) so use additional results
- additionalResult.results
- } else {
- // empty results but non-empty accumulator due to Hydrator being turned off so use accumulator results
- accumulator.results
- }
-
- CandidateFeatureHydratorExecutorResult(
- mergedFeatureMaps,
- accumulator.individualFeatureHydratorResults ++ additionalResult.individualFeatureHydratorResults
- )
- }
- }
-
- Arrow.ifelse[Inputs[Query, Result], CandidateFeatureHydratorExecutorResult[Result]](
- _.candidates.nonEmpty,
- runHydrators,
- Arrow.value(CandidateFeatureHydratorExecutorResult(Seq.empty, Map.empty)))
- }
-
- /** @note the returned [[Arrow]] must have a result for every candidate passed into it in the same order OR a completely empty result */
- private def getCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- hydrator: BaseCandidateFeatureHydrator[Query, Result, _],
- context: Executor.Context,
- candidateFeatureHydratorObserver: FeatureHydratorObserver
- ): Arrow[
- Inputs[Query, Result],
- CandidateFeatureHydratorExecutorResult[Result]
- ] = {
- val componentExecutorContext = context.pushToComponentStack(hydrator.identifier)
-
- val validateFeatureMapFn: FeatureMap => FeatureMap =
- hydrator match {
- // Feature store candidate hydrators store the resulting PredictionRecords and
- // not the features, so we cannot validate the same way
- case _: FeatureStoreV1CandidateFeatureHydrator[Query, Result] =>
- identity
- case _ =>
- validateFeatureMap(
- hydrator.features.asInstanceOf[Set[Feature[_, _]]],
- _,
- componentExecutorContext)
- }
-
- val hydratorBaseArrow = hydrator match {
- case hydrator: CandidateFeatureHydrator[Query, Result] =>
- singleCandidateHydratorArrow(
- hydrator,
- validateFeatureMapFn,
- componentExecutorContext,
- parentContext = context)
-
- case hydrator: BaseBulkCandidateFeatureHydrator[Query, Result, _] =>
- bulkCandidateHydratorArrow(
- hydrator,
- validateFeatureMapFn,
- componentExecutorContext,
- parentContext = context)
- }
-
- val candidateFeatureHydratorArrow =
- Arrow
- .zipWithArg(hydratorBaseArrow)
- .map {
- case (
- arg: CandidateFeatureHydratorExecutor.Inputs[Query, Result],
- featureMapSeq: Seq[FeatureMap]) =>
- val candidates = arg.candidates.map(_.candidate)
-
- candidateFeatureHydratorObserver.observeFeatureSuccessAndFailures(
- hydrator,
- featureMapSeq)
-
- // Build a map from candidate to FeatureMap
- val candidateAndFeatureMaps = if (candidates.size == featureMapSeq.size) {
- candidates.zip(featureMapSeq).map {
- case (candidate, featureMap) => HydratorCandidateResult(candidate, featureMap)
- }
- } else {
- throw PipelineFailure(
- MisconfiguredFeatureMapFailure,
- s"Unexpected response length from ${hydrator.identifier}, ensure hydrator returns feature map for all candidates")
- }
- val individualFeatureHydratorFeatureMaps =
- Map(hydrator.identifier -> IndividualFeatureHydratorResult(candidateAndFeatureMaps))
- CandidateFeatureHydratorExecutorResult(
- candidateAndFeatureMaps,
- individualFeatureHydratorFeatureMaps)
- }
-
- val conditionallyRunArrow = hydrator match {
- case hydrator: BaseCandidateFeatureHydrator[Query, Result, _] with Conditionally[
- Query @unchecked
- ] =>
- Arrow.ifelse[Inputs[Query, Result], CandidateFeatureHydratorExecutorResult[Result]](
- { case Inputs(query: Query @unchecked, _) => hydrator.onlyIf(query) },
- candidateFeatureHydratorArrow,
- Arrow.value(
- CandidateFeatureHydratorExecutorResult(
- Seq.empty,
- Map(hydrator.identifier -> FeatureHydratorDisabled[Result]())
- ))
- )
- case _ => candidateFeatureHydratorArrow
- }
-
- wrapWithErrorHandling(context, hydrator.identifier)(conditionallyRunArrow)
- }
-
- private def singleCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- hydrator: CandidateFeatureHydrator[Query, Result],
- validateFeatureMap: FeatureMap => FeatureMap,
- componentContext: Context,
- parentContext: Context
- ): Arrow[Inputs[Query, Result], Seq[FeatureMap]] = {
- val inputTransformer = Arrow
- .map { inputs: Inputs[Query, Result] =>
- inputs.candidates.map { candidate =>
- (inputs.query, candidate.candidate, candidate.features)
- }
- }
-
- val hydratorArrow = Arrow
- .flatMap[(Query, Result, FeatureMap), FeatureMap] {
- case (query, candidate, featureMap) =>
- hydrator.apply(query, candidate, featureMap)
- }
-
- // validate before observing so validation failures are caught in the metrics
- val hydratorArrowWithValidation = hydratorArrow.map(validateFeatureMap)
-
- // no tracing here since per-Component spans is overkill
- val observedArrow =
- wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing(
- parentContext,
- hydrator.identifier
- )(hydratorArrowWithValidation)
-
- // only handle non-validation failures
- val liftNonValidationFailuresToFailedFeatures = Arrow.handle[FeatureMap, FeatureMap] {
- case NotAMisconfiguredFeatureMapFailure(e) =>
- featureMapWithFailuresForFeatures(hydrator.features, e, componentContext)
- }
-
- wrapComponentsWithTracingOnly(parentContext, hydrator.identifier)(
- inputTransformer.andThen(
- Arrow.sequence(observedArrow.andThen(liftNonValidationFailuresToFailedFeatures))
- )
- )
- }
-
- private def bulkCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]](
- hydrator: BaseBulkCandidateFeatureHydrator[Query, Result, _],
- validateFeatureMap: FeatureMap => FeatureMap,
- componentContext: Context,
- parentContext: Context
- ): Arrow[Inputs[Query, Result], Seq[FeatureMap]] = {
- val hydratorArrow: Arrow[Inputs[Query, Result], Seq[FeatureMap]] =
- Arrow.flatMap { inputs =>
- hydrator.apply(inputs.query, inputs.candidates)
- }
-
- val validationArrow: Arrow[(Inputs[Query, Result], Seq[FeatureMap]), Seq[FeatureMap]] = Arrow
- .map[(Inputs[Query, Result], Seq[FeatureMap]), Seq[FeatureMap]] {
- case (inputs, results) =>
- // For bulk APIs, this ensures no candidates are omitted and also ensures the order is preserved.
- if (inputs.candidates.length != results.length) {
- throw PipelineFailure(
- MisconfiguredFeatureMapFailure,
- s"Unexpected response from ${hydrator.identifier}, ensure hydrator returns features for all candidates. Missing results for ${inputs.candidates.length - results.length} candidates"
- )
- }
-
- results.map(validateFeatureMap)
- }
-
- // validate before observing so validation failures are caught in the metrics
- val hydratorArrowWithValidation: Arrow[Inputs[Query, Result], Seq[FeatureMap]] =
- Arrow.zipWithArg(hydratorArrow).andThen(validationArrow)
-
- val observedArrow =
- wrapComponentWithExecutorBookkeeping(parentContext, hydrator.identifier)(
- hydratorArrowWithValidation)
-
- // only handle non-validation failures
- val liftNonValidationFailuresToFailedFeatures =
- Arrow.map[(Inputs[Query, Result], Try[Seq[FeatureMap]]), Try[Seq[FeatureMap]]] {
- case (inputs, resultTry) =>
- resultTry.handle {
- case NotAMisconfiguredFeatureMapFailure(e) =>
- val errorFeatureMap =
- featureMapWithFailuresForFeatures(
- hydrator.features.asInstanceOf[Set[Feature[_, _]]],
- e,
- componentContext)
- inputs.candidates.map(_ => errorFeatureMap)
- }
- }
-
- Arrow
- .zipWithArg(observedArrow.liftToTry)
- .andThen(liftNonValidationFailuresToFailedFeatures)
- .lowerFromTry
- }
-}
-
-object CandidateFeatureHydratorExecutor {
- case class Inputs[+Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- query: Query,
- candidates: Seq[CandidateWithFeatures[Candidate]])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala
deleted file mode 100644
index 9a865a7b0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor
-
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class CandidateFeatureHydratorExecutorResult[+Result <: UniversalNoun[Any]](
- results: Seq[CandidateWithFeatures[Result]],
- individualFeatureHydratorResults: Map[
- _ <: ComponentIdentifier,
- BaseIndividualFeatureHydratorResult[Result]
- ]) extends ExecutorResult
-
-sealed trait BaseIndividualFeatureHydratorResult[+Result <: UniversalNoun[Any]]
-case class FeatureHydratorDisabled[+Result <: UniversalNoun[Any]]()
- extends BaseIndividualFeatureHydratorResult[Result]
-case class IndividualFeatureHydratorResult[+Result <: UniversalNoun[Any]](
- result: Seq[CandidateWithFeatures[Result]])
- extends BaseIndividualFeatureHydratorResult[Result]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD
deleted file mode 100644
index 40702d280..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala
deleted file mode 100644
index 4c4ee849b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_feature_transformer_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor._
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CandidateFeatureTransformerExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
- def arrow[Result](
- transformers: Seq[CandidateFeatureTransformer[Result]],
- context: Executor.Context
- ): Arrow[Seq[Result], CandidateFeatureTransformerExecutorResult] = {
- if (transformers.isEmpty) {
- // must always return a Seq of FeatureMaps, even if there are no Transformers
- Arrow.map[Seq[Result], CandidateFeatureTransformerExecutorResult] { candidates =>
- CandidateFeatureTransformerExecutorResult(candidates.map(_ => FeatureMap.empty), Seq.empty)
- }
- } else {
- val transformerArrows: Seq[Arrow[Seq[Result], Seq[(TransformerIdentifier, FeatureMap)]]] =
- transformers.map { transformer =>
- val transformerContext = context.pushToComponentStack(transformer.identifier)
-
- val liftNonValidationFailuresToFailedFeatures =
- Arrow.handle[FeatureMap, FeatureMap] {
- case NotAMisconfiguredFeatureMapFailure(e) =>
- featureMapWithFailuresForFeatures(transformer.features, e, transformerContext)
- }
-
- val underlyingArrow = Arrow
- .map(transformer.transform)
- .map(validateFeatureMap(transformer.features, _, transformerContext))
-
- val observedArrowWithoutTracing =
- wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing(
- context,
- transformer.identifier)(underlyingArrow)
-
- val seqArrow =
- Arrow.sequence(
- observedArrowWithoutTracing
- .andThen(liftNonValidationFailuresToFailedFeatures)
- .map(transformer.identifier -> _)
- )
-
- wrapComponentsWithTracingOnly(context, transformer.identifier)(seqArrow)
- }
-
- Arrow.collect(transformerArrows).map { results =>
- /**
- * Inner Seqs are a given Transformer applied to all the candidates
- *
- * We want to merge the FeatureMaps for each candidate
- * from all the Transformers. We do this by merging all the FeatureMaps at
- * each index `i` of each Seq in `results` by `transpose`-ing the `results`
- * so the inner Seq becomes all the FeatureMaps for Candidate
- * at index `i` in the input Seq.
- *
- * {{{
- * Seq(
- * Seq(transformer1FeatureMapCandidate1, ..., transformer1FeatureMapCandidateN),
- * ...,
- * Seq(transformerMFeatureMapCandidate1, ..., transformerMFeatureMapCandidateN)
- * ).transpose == Seq(
- * Seq(transformer1FeatureMapCandidate1, ..., transformerMFeatureMapCandidate1),
- * ...,
- * Seq(transformer1FeatureMapCandidateN, ..., transformerMFeatureMapCandidateN)
- * )
- * }}}
- *
- * we could avoid the transpose if we ran each candidate through all the transformers
- * one-after-the-other, but then we couldn't have a single tracing span for all applications
- * of a Transformer, so instead we apply each transformer to all candidates together, then
- * move onto the next transformer.
- *
- * It's worth noting that the outer Seq is bounded by the number of Transformers that are
- * applied which will typically be small.
- */
- val transposed = results.transpose
- val combinedMaps = transposed.map(featureMapsForSingleCandidate =>
- FeatureMap.merge(featureMapsForSingleCandidate.map { case (_, maps) => maps }))
-
- CandidateFeatureTransformerExecutorResult(combinedMaps, transposed.map(_.toMap))
- }
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala
deleted file mode 100644
index 8947897a6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_feature_transformer_executor
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier
-
-case class CandidateFeatureTransformerExecutorResult(
- featureMaps: Seq[FeatureMap],
- individualFeatureMaps: Seq[Map[TransformerIdentifier, FeatureMap]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD
deleted file mode 100644
index f89ba2858..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala
deleted file mode 100644
index 6031d6e34..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_pipeline_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineResult
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-import com.twitter.util.logging.Logging
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class CandidatePipelineExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor
- with Logging {
-
- def arrow[Query <: PipelineQuery](
- candidatePipelines: Seq[CandidatePipeline[Query]],
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = {
-
- // Get the `.arrow` of each Candidate Pipeline, and wrap it in a ResultObserver
- val observedArrows: Seq[Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult]] =
- candidatePipelines.map { pipeline =>
- wrapPipelineWithExecutorBookkeeping(
- context = context,
- currentComponentIdentifier = pipeline.identifier,
- qualityFactorObserver = qualityFactorObserverByPipeline.get(pipeline.identifier),
- failOpenPolicy = failOpenPolicies.getOrElse(pipeline.identifier, defaultFailOpenPolicy)
- )(pipeline.arrow)
- }
-
- // Collect the results from all the candidate pipelines together
- Arrow.zipWithArg(Arrow.collect(observedArrows)).map {
- case (input: CandidatePipeline.Inputs[Query], results: Seq[CandidatePipelineResult]) =>
- val candidateWithDetails = results.flatMap(_.result.getOrElse(Seq.empty))
- val previousCandidateWithDetails = input.query.features
- .map(_.getOrElse(CandidatePipelineResults, Seq.empty))
- .getOrElse(Seq.empty)
-
- val featureMapWithCandidates = FeatureMapBuilder()
- .add(CandidatePipelineResults, previousCandidateWithDetails ++ candidateWithDetails)
- .build()
-
- // Merge the query feature hydrator and candidate source query features back in. While this
- // is done internally in the pipeline, we have to pass it back since we don't expose the
- // updated pipeline query today.
- val queryFeatureHydratorFeatureMaps =
- results
- .flatMap(result => Seq(result.queryFeatures, result.queryFeaturesPhase2))
- .collect { case Some(result) => result.featureMap }
- val asyncFeatureHydratorFeatureMaps =
- results
- .flatMap(_.asyncFeatureHydrationResults)
- .flatMap(_.featureMapsByStep.values)
-
- val candidateSourceFeatureMaps =
- results
- .flatMap(_.candidateSourceResult)
- .map(_.candidateSourceFeatureMap)
-
- val featureMaps =
- (featureMapWithCandidates +: queryFeatureHydratorFeatureMaps) ++ asyncFeatureHydratorFeatureMaps ++ candidateSourceFeatureMaps
- val mergedFeatureMap = FeatureMap.merge(featureMaps)
- CandidatePipelineExecutorResult(
- candidatePipelineResults = results,
- queryFeatureMap = mergedFeatureMap)
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala
deleted file mode 100644
index 8f3805f2f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_pipeline_executor
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineResult
-
-case class CandidatePipelineExecutorResult(
- candidatePipelineResults: Seq[CandidatePipelineResult],
- queryFeatureMap: FeatureMap)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD
deleted file mode 100644
index c34688181..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala
deleted file mode 100644
index 5d6df2678..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_source_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures
-import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures
-import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer
-import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSources
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ExecutionFailed
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.candidate_feature_transformer_executor.CandidateFeatureTransformerExecutor
-import com.twitter.product_mixer.core.service.transformer_executor.PerCandidateTransformerExecutor
-import com.twitter.product_mixer.core.service.transformer_executor.TransformerExecutor
-import com.twitter.stitch.Arrow
-import com.twitter.util.Return
-import com.twitter.util.Throw
-import com.twitter.util.Try
-import com.twitter.util.logging.Logging
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.immutable.ListSet
-
-/**
- * [[CandidateSourceExecutor]]:
- * - Executes a [[BaseCandidateSource]], using a [[BaseCandidatePipelineQueryTransformer]] and a [[CandidatePipelineResultsTransformer]]
- * - in parallel, uses a [[CandidateFeatureTransformer]] to optionally extract [[com.twitter.product_mixer.core.feature.Feature]]s from the result
- * - Handles [[UnexpectedCandidateResult]] [[PipelineFailure]]s returned from [[CandidatePipelineResultsTransformer]] failures by removing those candidates from the result
- */
-@Singleton
-class CandidateSourceExecutor @Inject() (
- override val statsReceiver: StatsReceiver,
- candidateFeatureTransformerExecutor: CandidateFeatureTransformerExecutor,
- transformerExecutor: TransformerExecutor,
- perCandidateTransformerExecutor: PerCandidateTransformerExecutor)
- extends Executor
- with Logging {
-
- def arrow[
- Query <: PipelineQuery,
- CandidateSourceQuery,
- CandidateSourceResult,
- Candidate <: UniversalNoun[Any]
- ](
- candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult],
- queryTransformer: BaseCandidatePipelineQueryTransformer[
- Query,
- CandidateSourceQuery
- ],
- resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Candidate],
- resultFeaturesTransformers: Seq[CandidateFeatureTransformer[CandidateSourceResult]],
- context: Executor.Context
- ): Arrow[Query, CandidateSourceExecutorResult[Candidate]] = {
-
- val candidateSourceArrow: Arrow[CandidateSourceQuery, CandidatesWithSourceFeatures[
- CandidateSourceResult
- ]] =
- candidateSource match {
- case regularCandidateSource: CandidateSource[CandidateSourceQuery, CandidateSourceResult] =>
- Arrow.flatMap(regularCandidateSource.apply).map { candidates =>
- CandidatesWithSourceFeatures(candidates, FeatureMap.empty)
- }
- case candidateSourceWithExtractedFeatures: CandidateSourceWithExtractedFeatures[
- CandidateSourceQuery,
- CandidateSourceResult
- ] =>
- Arrow.flatMap(candidateSourceWithExtractedFeatures.apply)
- }
-
- val resultsTransformerArrow: Arrow[Seq[CandidateSourceResult], Seq[Try[Candidate]]] =
- perCandidateTransformerExecutor.arrow(resultTransformer, context)
-
- val featureMapTransformersArrow: Arrow[
- Seq[CandidateSourceResult],
- Seq[FeatureMap]
- ] =
- candidateFeatureTransformerExecutor
- .arrow(resultFeaturesTransformers, context).map(_.featureMaps)
-
- val candidatesResultArrow: Arrow[CandidatesWithSourceFeatures[CandidateSourceResult], Seq[
- (Candidate, FeatureMap)
- ]] = Arrow
- .map[CandidatesWithSourceFeatures[CandidateSourceResult], Seq[CandidateSourceResult]](
- _.candidates)
- .andThen(Arrow
- .joinMap(resultsTransformerArrow, featureMapTransformersArrow) {
- case (transformed, features) =>
- if (transformed.length != features.length)
- throw PipelineFailure(
- ExecutionFailed,
- s"Found ${transformed.length} candidates and ${features.length} FeatureMaps, expected their lengths to be equal")
- transformed.iterator
- .zip(features.iterator)
- .collect { case ErrorHandling(result) => result }
- .toSeq
- })
-
- // Build the final CandidateSourceExecutorResult
- val executorResultArrow: Arrow[
- (FeatureMap, Seq[(Candidate, FeatureMap)]),
- CandidateSourceExecutorResult[
- Candidate
- ]
- ] = Arrow.map {
- case (queryFeatures: FeatureMap, results: Seq[(Candidate, FeatureMap)]) =>
- val candidatesWithFeatures: Seq[FetchedCandidateWithFeatures[Candidate]] =
- results.zipWithIndex.map {
- case ((candidate, featureMap), index) =>
- FetchedCandidateWithFeatures(
- candidate,
- featureMap + (CandidateSourcePosition, index) + (CandidateSources, ListSet(
- candidateSource.identifier))
- )
- }
- CandidateSourceExecutorResult(
- candidates = candidatesWithFeatures,
- candidateSourceFeatureMap = queryFeatures
- )
- }
-
- val queryTransformerArrow =
- transformerExecutor.arrow[Query, CandidateSourceQuery](queryTransformer, context)
-
- val combinedArrow =
- queryTransformerArrow
- .andThen(candidateSourceArrow)
- .andThen(
- Arrow
- .join(
- Arrow.map[CandidatesWithSourceFeatures[CandidateSourceResult], FeatureMap](
- _.features),
- candidatesResultArrow
- ))
- .andThen(executorResultArrow)
-
- wrapComponentWithExecutorBookkeepingWithSize[Query, CandidateSourceExecutorResult[Candidate]](
- context,
- candidateSource.identifier,
- result => result.candidates.size
- )(combinedArrow)
- }
-
- object ErrorHandling {
-
- /** Silently drop [[UnexpectedCandidateResult]] */
- def unapply[Candidate](
- candidateTryAndFeatureMap: (Try[Candidate], FeatureMap)
- ): Option[(Candidate, FeatureMap)] = {
- val (candidateTry, featureMap) = candidateTryAndFeatureMap
- val candidateOpt = candidateTry match {
- case Throw(PipelineFailure(UnexpectedCandidateResult, _, _, _)) => None
- case Throw(ex) => throw ex
- case Return(r) => Some(r)
- }
-
- candidateOpt.map { candidate => (candidate, featureMap) }
- }
- }
-}
-
-case class FetchedCandidateWithFeatures[Candidate <: UniversalNoun[Any]](
- candidate: Candidate,
- features: FeatureMap)
- extends CandidateWithFeatures[Candidate]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala
deleted file mode 100644
index 451bae1ae..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.service.candidate_source_executor
-
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class CandidateSourceExecutorResult[Candidate <: UniversalNoun[Any]](
- candidates: Seq[FetchedCandidateWithFeatures[Candidate]],
- candidateSourceFeatureMap: FeatureMap)
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD
deleted file mode 100644
index 34d6b7fda..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "util/util-slf4j-api",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala
deleted file mode 100644
index 14b70aa84..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala
+++ /dev/null
@@ -1,182 +0,0 @@
-package com.twitter.product_mixer.core.service.component_registry
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.util.Activity
-import com.twitter.util.Future
-import com.twitter.util.Try
-import com.twitter.util.logging.Logging
-import java.util.concurrent.ConcurrentHashMap
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.JavaConverters._
-
-/**
- * The [[ComponentRegistry]] works closely with [[ComponentIdentifier]]s and the [[com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry]]
- * to provide the Product Mixer framework information about the [[com.twitter.product_mixer.core.pipeline.Pipeline]]s and [[Component]]s
- * that make up an application.
- *
- * This registration allows us to configure alerts and dashboards,
- * to query your application structure letting us display the graph of the execution and the results of queries,
- * and to garner insight into usages.
- *
- * The registry is a snapshot of the state of the world when pipelines were last built successfully.
- * For most services, this only happens once on startup. However, some services may rebuild their
- * pipelines dynamically later on.
- */
-
-@Singleton
-class ComponentRegistry @Inject() (statsReceiver: StatsReceiver) {
- // Initially pending until the first snapshot is built by [[ProductPipelineRegistry]]
- private val (snapshotActivity, snapshotWitness) = Activity[ComponentRegistrySnapshot]()
- private val snapshotCount = statsReceiver.counter("ComponentRegistry", "SnapshotCount")
-
- def get: Future[ComponentRegistrySnapshot] = snapshotActivity.values.toFuture.lowerFromTry
- private[core] def set(snapshot: ComponentRegistrySnapshot): Unit = {
- snapshotCount.incr()
- snapshotWitness.notify(Try(snapshot))
- }
-}
-
-class ComponentRegistrySnapshot() extends Logging {
-
- /** for storing the [[RegisteredComponent]]s */
- private[this] val componentRegistry =
- new ConcurrentHashMap[ComponentIdentifier, RegisteredComponent]
-
- /** for determining the children of a [[ComponentIdentifier]] */
- private[this] val componentChildren =
- new ConcurrentHashMap[ComponentIdentifier, Set[ComponentIdentifier]]
-
- /** for determining [[ComponentIdentifier]] uniqueness within a given [[ComponentIdentifierStack]] */
- private[this] val componentHierarchy =
- new ConcurrentHashMap[ComponentIdentifierStack, Set[ComponentIdentifier]]
-
- /**
- * Register the given [[Component]] at the end of path provided by `parentIdentifierStack`
- * or throws an exception if adding the component results in an invalid configuration.
- *
- * @throws ChildComponentCollisionException if a [[Component]] with the same [[ComponentIdentifier]] is registered
- * more than once under the same parent.
- * e.g. if you register `ComponentA` under `ProductA -> PipelineA` twice,
- * this exception will be thrown when registering `ComponentA` the second
- * time. This is pretty much always a configuration error due to copy-pasting
- * and forgetting to update the identifier, or accidentally using the same
- * component twice under the same parent. If this didn't throw, stats from
- * these 2 components would be indistinguishable.
- *
- * @throws ComponentIdentifierCollisionException if a [[Component]] with the same [[ComponentIdentifier]] is registered
- * but it's type is not the same as a previously registered [[Component]]
- * with the same [[ComponentIdentifier]]
- * e.g. if you register 2 [[Component]]s with the same [[ComponentIdentifier]]
- * such as `new Component` and an instance of
- * `class MyComponent extends Component` the `new Component` will have a
- * type of `Component` and the other one will have a type of `MyComponent`
- * which will throw. This is usually due to copy-pasting a component as
- * a starting point and forgetting to update the identifier. If this
- * didn't throw, absolute stats from these 2 components would be
- * indistinguishable.
- *
- *
- * @note this will log details of component identifier reuse if the underling components are not equal, but otherwise are of the same class.
- * Their stats will be merged and indistinguishable but since they are the same name and same class, we assume the differences are
- * minor enough that this is okay, but make a note in the log at startup in case someone sees unexpected metrics, we can look
- * back at the logs and see the details.
- *
- * @param component the component to register
- * @param parentIdentifierStack the complete [[ComponentIdentifierStack]] excluding the current [[Component]]'s [[ComponentIdentifier]]
- */
- def register(
- component: Component,
- parentIdentifierStack: ComponentIdentifierStack
- ): Unit = synchronized {
- val identifier = component.identifier
- val parentIdentifier = parentIdentifierStack.peek
-
- val registeredComponent =
- RegisteredComponent(identifier, component, component.identifier.file.value)
-
- componentRegistry.asScala
- .get(identifier)
- .filter(_.component != component) // only do the foreach if the components aren't equal
- .foreach {
- case existingComponent if existingComponent.component.getClass != component.getClass =>
- /**
- * The same component may be registered under different parent components.
- * However, different component types cannot use the same component identifier.
- *
- * This catches some copy-pasting of a config or component and forgetting to update the identifier.
- */
- throw new ComponentIdentifierCollisionException(
- componentIdentifier = identifier,
- component = registeredComponent,
- existingComponent = componentRegistry.get(identifier),
- parentIdentifierStack = parentIdentifierStack,
- existingIdentifierStack = componentHierarchy.search[ComponentIdentifierStack](
- 1,
- (stack, identifiers) => if (identifiers.contains(identifier)) stack else null)
- )
- case existingComponent =>
- /**
- * The same component may be registered under different parent components.
- * However, if the components are not equal it __may be__ a configuration error
- * so we log a detailed description of the issue in case they need to debug.
- *
- * This warns customers of some copy-pasting of a config or component and forgetting to update the
- * identifier and of reusing components with hard-coded values which are configured differently.
- */
- val existingIdentifierStack = componentHierarchy.search[ComponentIdentifierStack](
- 1,
- (stack, identifiers) => if (identifiers.contains(identifier)) stack else null)
- logger.info(
- s"Found duplicate identifiers for non-equal components, $identifier from ${registeredComponent.sourceFile} " +
- s"under ${parentIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")} " +
- s"was already defined and is unequal to ${existingComponent.sourceFile} " +
- s"under ${existingIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")}. " +
- s"Merging these components in the registry, this will result in their metrics being merged. " +
- s"If these components should have separate metrics, consider providing unique identifiers for them instead."
- )
- }
-
- /** The same component may not be registered multiple times under the same parent */
- if (componentHierarchy.getOrDefault(parentIdentifierStack, Set.empty).contains(identifier))
- throw new ChildComponentCollisionException(identifier, parentIdentifierStack)
-
- // add component to registry
- componentRegistry.putIfAbsent(identifier, registeredComponent)
- // add component to parent's `children` set for easy lookup
- componentChildren.merge(parentIdentifier, Set(identifier), _ ++ _)
- // add the component to the hierarchy under it's parent's identifier stack
- componentHierarchy.merge(parentIdentifierStack, Set(identifier), _ ++ _)
- }
-
- def getAllRegisteredComponents: Seq[RegisteredComponent] =
- componentRegistry.values.asScala.toSeq.sorted
-
- def getChildComponents(component: ComponentIdentifier): Seq[ComponentIdentifier] =
- Option(componentChildren.get(component)) match {
- case Some(components) => components.toSeq.sorted(ComponentIdentifier.ordering)
- case None => Seq.empty
- }
-}
-
-class ComponentIdentifierCollisionException(
- componentIdentifier: ComponentIdentifier,
- component: RegisteredComponent,
- existingComponent: RegisteredComponent,
- parentIdentifierStack: ComponentIdentifierStack,
- existingIdentifierStack: ComponentIdentifierStack)
- extends IllegalArgumentException(
- s"Tried to register component $componentIdentifier: of type ${component.component.getClass} from ${component.sourceFile} " +
- s"under ${parentIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")} " +
- s"but it was already defined with a different type ${existingComponent.component.getClass} from ${existingComponent.sourceFile} " +
- s"under ${existingIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")}. " +
- s"Ensure you aren't reusing a component identifier which can happen when copy-pasting existing component code by accident")
-
-class ChildComponentCollisionException(
- componentIdentifier: ComponentIdentifier,
- parentIdentifierStack: ComponentIdentifierStack)
- extends IllegalArgumentException(
- s"Component $componentIdentifier already defined under parent component $parentIdentifierStack")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala
deleted file mode 100644
index 6ddadc033..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.twitter.product_mixer.core.service.component_registry
-
-import com.twitter.product_mixer.core.model.common.Component
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-
-object RegisteredComponent {
- // Sort by ComponentIdentifier which has its own implicit ordering defined
- implicit val ordering: Ordering[RegisteredComponent] =
- Ordering.by[RegisteredComponent, ComponentIdentifier](_.component.identifier)
-}
-
-case class RegisteredComponent(
- identifier: ComponentIdentifier,
- component: Component,
- sourceFile: String)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala
deleted file mode 100644
index 4c0aa8b88..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.twitter.product_mixer.core.service.debug_query
-
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy
-import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicyEvaluator
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.Authentication
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.turntable.{thriftscala => t}
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Basic class that provides a verification method for checking if a call to our debugging
- * features is allowed/authorized to make said call.
- * @param isServiceLocal Whether the service is being run locally.
- */
-@Singleton
-class AuthorizationService @Inject() (@Flag(ServiceLocal) isServiceLocal: Boolean) {
- import AuthorizationService._
-
- /**
- * Check whether a call to a given product is authorized. Throws an [[UnauthorizedServiceCallException]]
- * if not.
- * @param requestingServiceIdentifier The Service Identifier of the calling service
- * @param productAccessPolicies The access policies of the product being called.
- * @param requestContext The request context of the caller.
- */
- def verifyRequestAuthorization(
- componentIdentifierStack: ComponentIdentifierStack,
- requestingServiceIdentifier: ServiceIdentifier,
- productAccessPolicies: Set[AccessPolicy],
- requestContext: t.TurntableRequestContext
- ): Unit = {
- val isServiceCallAuthorized =
- requestingServiceIdentifier.role == AllowedServiceIdentifierRole && requestingServiceIdentifier.service == AllowedServiceIdentifierName
- val userLdapGroups = requestContext.ldapGroups.map(_.toSet)
-
- val accessPolicyAllowed = AccessPolicyEvaluator.evaluate(
- productAccessPolicies = productAccessPolicies,
- userLdapGroups = userLdapGroups.getOrElse(Set.empty)
- )
-
- if (!isServiceLocal && !isServiceCallAuthorized) {
- throw new UnauthorizedServiceCallException(
- requestingServiceIdentifier,
- componentIdentifierStack)
- }
-
- if (!isServiceLocal && !accessPolicyAllowed) {
- throw new InsufficientAccessException(
- userLdapGroups,
- productAccessPolicies,
- componentIdentifierStack)
- }
- }
-}
-
-object AuthorizationService {
- final val AllowedServiceIdentifierRole = "turntable"
- final val AllowedServiceIdentifierName = "turntable"
-}
-
-class UnauthorizedServiceCallException(
- serviceIdentifier: ServiceIdentifier,
- componentIdentifierStack: ComponentIdentifierStack)
- extends PipelineFailure(
- BadRequest,
- s"Unexpected Service tried to call Turntable Debug endpoint: ${ServiceIdentifier.asString(serviceIdentifier)}",
- componentStack = Some(componentIdentifierStack))
-
-class InsufficientAccessException(
- ldapGroups: Option[Set[String]],
- desiredAccessPolicies: Set[AccessPolicy],
- componentIdentifierStack: ComponentIdentifierStack)
- extends PipelineFailure(
- Authentication,
- s"Request did not satisfy access policies: $desiredAccessPolicies with ldapGroups = $ldapGroups",
- componentStack = Some(componentIdentifierStack))
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD
deleted file mode 100644
index 251996247..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD
+++ /dev/null
@@ -1,20 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala",
- "product-mixer/turntable/service/src/main/scala/com/twitter/turntable/context:key",
- "stitch/stitch-core",
- "util/util-core:scala",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala
deleted file mode 100644
index 22870d3d5..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.twitter.product_mixer.core.service.debug_query
-
-import com.twitter.finagle.Service
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineResult
-import com.twitter.scrooge.{Request => ScroogeRequest}
-import com.twitter.scrooge.{Response => ScroogeResponse}
-import com.twitter.util.Future
-import com.twitter.product_mixer.core.{thriftscala => t}
-import com.twitter.util.jackson.ScalaObjectMapper
-
-/**
- * All Mixers must implement a debug query interface. This can be a problem for in-place migrations
- * where a service may only partially implement Product Mixer patterns. This service can be used as
- * a noop implementation of [[DebugQueryService]] until the Mixer service is fully migrated.
- */
-object DebugQueryNotSupportedService
- extends Service[ScroogeRequest[_], ScroogeResponse[t.PipelineExecutionResult]] {
-
- val failureJson: String = {
- val message = "This service does not support debug queries, this is usually due to an active " +
- "in-place migration to Product Mixer. Please reach out in #product-mixer if you have any questions."
-
- ScalaObjectMapper().writeValueAsString(
- ProductPipelineResult(
- transformedQuery = None,
- qualityFactorResult = None,
- gateResult = None,
- pipelineSelectorResult = None,
- mixerPipelineResult = None,
- recommendationPipelineResult = None,
- traceId = None,
- failure = Some(PipelineFailure(ProductDisabled, message)),
- result = None,
- ))
- }
-
- override def apply(
- thriftRequest: ScroogeRequest[_]
- ): Future[ScroogeResponse[t.PipelineExecutionResult]] =
- Future.value(ScroogeResponse(t.PipelineExecutionResult(failureJson)))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala
deleted file mode 100644
index 9a8f5f413..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.twitter.product_mixer.core.service.debug_query
-
-import com.fasterxml.jackson.databind.SerializationFeature
-import com.twitter.finagle.Service
-import com.twitter.finagle.context.Contexts
-import com.twitter.finagle.tracing.Trace.traceLocal
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.transport.Transport
-import com.twitter.product_mixer.core.functional_component.configapi.ParamsBuilder
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack
-import com.twitter.product_mixer.core.model.marshalling.request.Product
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.product.ProductPipeline
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest
-import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry
-import com.twitter.product_mixer.core.{thriftscala => t}
-import com.twitter.scrooge.ThriftStruct
-import com.twitter.scrooge.{Request => ScroogeRequest}
-import com.twitter.scrooge.{Response => ScroogeResponse}
-import com.twitter.stitch.Stitch
-import com.twitter.turntable.context.TurntableRequestContextKey
-import com.twitter.util.jackson.ScalaObjectMapper
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.reflect.runtime.universe.TypeTag
-
-/**
- * Returns the complete execution log for a pipeline query. These endpoints are intended for
- * debugging (primarily through Turntable).
- */
-@Singleton
-class DebugQueryService @Inject() (
- productPipelineRegistry: ProductPipelineRegistry,
- paramsBuilder: ParamsBuilder,
- authorizationService: AuthorizationService) {
-
- private val mapper =
- ScalaObjectMapper.builder
- .withAdditionalJacksonModules(Seq(ParamsSerializerModule))
- .withSerializationConfig(
- Map(
- // These are copied from the default serialization config.
- SerializationFeature.WRITE_DATES_AS_TIMESTAMPS -> false,
- SerializationFeature.WRITE_ENUMS_USING_TO_STRING -> true,
- // Generally we want to be defensive when serializing since we don't control everything that's
- // serialized. This issue also came up when trying to serialize Unit as part of sync side effects.
- SerializationFeature.FAIL_ON_EMPTY_BEANS -> false,
- ))
- // The default implementation represents numbers as JSON Numbers (i.e. Double with 53 bit precision
- // which leads to Snowflake IDs being cropped in the case of tweets.
- .withNumbersAsStrings(true)
- .objectMapper
-
- def apply[
- ThriftRequest <: ThriftStruct with Product1[MixerServiceRequest],
- MixerServiceRequest <: ThriftStruct,
- MixerRequest <: Request
- ](
- unmarshaller: MixerServiceRequest => MixerRequest
- )(
- implicit requestTypeTag: TypeTag[MixerRequest]
- ): Service[ScroogeRequest[ThriftRequest], ScroogeResponse[t.PipelineExecutionResult]] = {
- (thriftRequest: ScroogeRequest[ThriftRequest]) =>
- {
-
- val request = unmarshaller(thriftRequest.args._1)
- val params = paramsBuilder.build(
- clientContext = request.clientContext,
- product = request.product,
- featureOverrides = request.debugParams.flatMap(_.featureOverrides).getOrElse(Map.empty)
- )
-
- val productPipeline = productPipelineRegistry
- .getProductPipeline[MixerRequest, Any](request.product)
- verifyRequestAuthorization(request.product, productPipeline)
- Contexts.broadcast.letClear(TurntableRequestContextKey) {
- Stitch
- .run(productPipeline
- .arrow(ProductPipelineRequest(request, params)).map { detailedResult =>
- // Serialization can be slow so a trace is useful both for optimization by the Promix
- // team and to give visibility to customers.
- val serializedJSON =
- traceLocal("serialize_debug_response")(mapper.writeValueAsString(detailedResult))
- t.PipelineExecutionResult(serializedJSON)
- })
- .map(ScroogeResponse(_))
- }
- }
- }
-
- private def verifyRequestAuthorization(
- product: Product,
- productPipeline: ProductPipeline[_, _]
- ): Unit = {
- val serviceIdentifier = ServiceIdentifier.fromCertificate(Transport.peerCertificate)
- val requestContext = Contexts.broadcast
- .get(TurntableRequestContextKey).getOrElse(throw MissingTurntableRequestContextException)
-
- val componentStack = ComponentIdentifierStack(productPipeline.identifier, product.identifier)
- authorizationService.verifyRequestAuthorization(
- componentStack,
- serviceIdentifier,
- productPipeline.debugAccessPolicies,
- requestContext)
- }
-}
-
-object MissingTurntableRequestContextException
- extends Exception("Request is missing turntable request context")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala
deleted file mode 100644
index e7265378f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.service.debug_query
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.fasterxml.jackson.databind.ser.std.StdSerializer
-import com.twitter.timelines.configapi.Params
-import com.fasterxml.jackson.databind.module.SimpleModule
-import com.twitter.timelines.configapi.Config
-
-object ParamsSerializerModule extends SimpleModule {
- addSerializer(ParamsConfigSerializer)
- addSerializer(ParamsStdSerializer)
-}
-
-object ParamsStdSerializer extends StdSerializer[Params](classOf[Params]) {
- override def serialize(
- value: Params,
- gen: JsonGenerator,
- provider: SerializerProvider
- ): Unit = {
- gen.writeStartObject()
- gen.writeObjectField("applied_params", value.allAppliedValues)
- gen.writeEndObject()
- }
-}
-
-object ParamsConfigSerializer extends StdSerializer[Config](classOf[Config]) {
- override def serialize(
- value: Config,
- gen: JsonGenerator,
- provider: SerializerProvider
- ): Unit = {
- gen.writeString(value.simpleName)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD
deleted file mode 100644
index a56fdf2f4..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala
deleted file mode 100644
index f0dc0e263..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.twitter.product_mixer.core.service.domain_marshaller_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor.Inputs
-import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor.Result
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Executes a [[DomainMarshaller]].
- *
- * @note This is a synchronous transform, so we don't observe it directly. Failures and such
- * can be observed at the parent pipeline.
- */
-@Singleton
-class DomainMarshallerExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
- def arrow[Query <: PipelineQuery, DomainResponseType <: HasMarshalling](
- marshaller: DomainMarshaller[Query, DomainResponseType],
- context: Executor.Context
- ): Arrow[Inputs[Query], Result[DomainResponseType]] = {
- val arrow = Arrow
- .map[Inputs[Query], DomainMarshallerExecutor.Result[DomainResponseType]] {
- case Inputs(query, candidates) =>
- DomainMarshallerExecutor.Result(marshaller(query, candidates))
- }
-
- wrapComponentWithExecutorBookkeeping(context, marshaller.identifier)(arrow)
- }
-}
-
-object DomainMarshallerExecutor {
- case class Inputs[Query <: PipelineQuery](
- query: Query,
- candidatesWithDetails: Seq[CandidateWithDetails])
- case class Result[+DomainResponseType](result: DomainResponseType) extends ExecutorResult
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD
deleted file mode 100644
index f3991968f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD
+++ /dev/null
@@ -1,21 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala
deleted file mode 100644
index b37134907..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.twitter.product_mixer.core.service.feature_hydrator_observer
-
-import com.twitter.finagle.stats.BroadcastStatsReceiver
-import com.twitter.finagle.stats.Counter
-import com.twitter.finagle.stats.RollupStatsReceiver
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.ml.featurestore.lib.data.HydrationError
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.shared_library.observer.Observer
-import com.twitter.servo.util.CancelledExceptionExtractor
-import com.twitter.util.Throw
-import com.twitter.util.Throwables
-
-class FeatureHydratorObserver(
- statsReceiver: StatsReceiver,
- hydrators: Seq[FeatureHydrator[_]],
- context: Executor.Context) {
-
- private val hydratorAndFeatureToStats: Map[
- ComponentIdentifier,
- Map[Feature[_, _], FeatureCounters]
- ] =
- hydrators.map { hydrator =>
- val hydratorScope = Executor.buildScopes(context, hydrator.identifier)
- val featureToCounterMap: Map[Feature[_, _], FeatureCounters] = hydrator.features
- .asInstanceOf[Set[Feature[_, _]]].map { feature =>
- val scopedStats = scopedBroadcastStats(hydratorScope, feature)
- // Initialize so we have them registered
- val requestsCounter = scopedStats.counter(Observer.Requests)
- val successCounter = scopedStats.counter(Observer.Success)
- // These are dynamic so we can't really cache them
- scopedStats.counter(Observer.Failures)
- scopedStats.counter(Observer.Cancelled)
- feature -> FeatureCounters(requestsCounter, successCounter, scopedStats)
- }.toMap
- hydrator.identifier -> featureToCounterMap
- }.toMap
-
- def observeFeatureSuccessAndFailures(
- hydrator: FeatureHydrator[_],
- featureMaps: Seq[FeatureMap]
- ): Unit = {
-
- val features = hydrator.features.asInstanceOf[Set[Feature[_, _]]]
-
- val failedFeaturesWithErrorNames: Map[Feature[_, _], Seq[Seq[String]]] = hydrator match {
- case _: FeatureStoreV1QueryFeatureHydrator[_] |
- _: FeatureStoreV1CandidateFeatureHydrator[_, _] =>
- featureMaps.toIterator
- .flatMap(_.getTry(FeatureStoreV1ResponseFeature).toOption.map(_.failedFeatures)).flatMap {
- failureMap: Map[_ <: Feature[_, _], Set[HydrationError]] =>
- failureMap.flatMap {
- case (feature, errors: Set[HydrationError]) =>
- errors.headOption.map { error =>
- feature -> Seq(Observer.Failures, error.errorType)
- }
- }.toIterator
- }.toSeq.groupBy { case (feature, _) => feature }.mapValues { seqOfTuples =>
- seqOfTuples.map { case (_, error) => error }
- }
-
- case _: FeatureHydrator[_] =>
- features.toIterator
- .flatMap { feature =>
- featureMaps
- .flatMap(_.underlyingMap
- .get(feature).collect {
- case Throw(CancelledExceptionExtractor(throwable)) =>
- (feature, Observer.Cancelled +: Throwables.mkString(throwable))
- case Throw(throwable) =>
- (feature, Observer.Failures +: Throwables.mkString(throwable))
- })
- }.toSeq.groupBy { case (feature, _) => feature }.mapValues { seqOfTuples =>
- seqOfTuples.map { case (_, error) => error }
- }
- }
-
- val failedFeaturesWithErrorCountsMap: Map[Feature[_, _], Map[Seq[String], Int]] =
- failedFeaturesWithErrorNames.mapValues(_.groupBy { statKey => statKey }.mapValues(_.size))
-
- val featuresToCounterMap = hydratorAndFeatureToStats.getOrElse(
- hydrator.identifier,
- throw new MissingHydratorException(hydrator.identifier))
- features.foreach { feature =>
- val hydratorFeatureCounters: FeatureCounters = featuresToCounterMap.getOrElse(
- feature,
- throw new MissingFeatureException(hydrator.identifier, feature))
- val failedMapsCount = failedFeaturesWithErrorNames.getOrElse(feature, Seq.empty).size
- val failedFeatureErrorCounts = failedFeaturesWithErrorCountsMap.getOrElse(feature, Map.empty)
-
- hydratorFeatureCounters.requestsCounter.incr(featureMaps.size)
- hydratorFeatureCounters.successCounter.incr(featureMaps.size - failedMapsCount)
- failedFeatureErrorCounts.foreach {
- case (failure, count) =>
- hydratorFeatureCounters.scopedStats.counter(failure: _*).incr(count)
- }
- }
- }
-
- private def scopedBroadcastStats(
- hydratorScope: Executor.Scopes,
- feature: Feature[_, _],
- ): StatsReceiver = {
- val suffix = Seq("Feature", feature.toString)
- val localScope = hydratorScope.componentScopes ++ suffix
- val relativeScope = hydratorScope.relativeScope ++ suffix
- new RollupStatsReceiver(
- BroadcastStatsReceiver(
- Seq(
- statsReceiver.scope(localScope: _*),
- statsReceiver.scope(relativeScope: _*),
- )
- ))
- }
-}
-
-case class FeatureCounters(
- requestsCounter: Counter,
- successCounter: Counter,
- scopedStats: StatsReceiver)
-
-class MissingHydratorException(featureHydratorIdentifier: ComponentIdentifier)
- extends Exception(s"Missing Feature Hydrator in Stats Map: ${featureHydratorIdentifier.name}")
-
-class MissingFeatureException(
- featureHydratorIdentifier: ComponentIdentifier,
- feature: Feature[_, _])
- extends Exception(
- s"Missing Feature in Stats Map: ${feature.toString} for ${featureHydratorIdentifier.name}")
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD
deleted file mode 100644
index 313fde03c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala
deleted file mode 100644
index 2d463e90b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala
+++ /dev/null
@@ -1,172 +0,0 @@
-package com.twitter.product_mixer.core.service.filter_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.filter.Filter
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor.FilterState
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Arrow.Iso
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.immutable.Queue
-
-/**
- * Applies a `Seq[Filter]` in sequential order.
- * Returns the results and a detailed Seq of each filter's results (for debugging / coherence).
- *
- * Note that each successive filter is only passed the 'kept' Seq from the previous filter, not the full
- * set of candidates.
- */
-@Singleton
-class FilterExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor {
-
- private val Kept = "kept"
- private val Removed = "removed"
-
- def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- filters: Seq[Filter[Query, Candidate]],
- context: Executor.Context
- ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] = {
-
- val filterArrows = filters.map(getIsoArrowForFilter(_, context))
- val combinedArrow = isoArrowsSequentially(filterArrows)
-
- Arrow
- .map[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterState[Query, Candidate]] {
- case (query, filterCandidates) =>
- // transform the input to the initial state of a `FilterExecutorResult`
- val initialFilterExecutorResult =
- FilterExecutorResult(filterCandidates.map(_.candidate), Queue.empty)
- val allCandidates: Map[Candidate, CandidateWithFeatures[Candidate]] =
- filterCandidates.map { fc =>
- (fc.candidate, fc)
- }.toMap
-
- FilterState(query, allCandidates, initialFilterExecutorResult)
- }
- .flatMapArrow(combinedArrow)
- .map {
- case FilterState(_, _, filterExecutorResult) =>
- filterExecutorResult.copy(individualFilterResults =
- // materialize the Queue into a List for faster future iterations
- filterExecutorResult.individualFilterResults.toList)
- }
-
- }
-
- /**
- * Adds filter specific stats, generic [[wrapComponentWithExecutorBookkeeping]] stats, and wraps with failure handling
- *
- * If the filter is a [[Conditionally]] ensures that we dont record stats if its turned off
- *
- * @note For performance, the [[FilterExecutorResult.individualFilterResults]] is build backwards - the head being the most recent result.
- * @param filter the filter to make an [[Arrow]] out of
- * @param context the [[Executor.Context]] for the pipeline this is a part of
- */
- private def getIsoArrowForFilter[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- filter: Filter[Query, Candidate],
- context: Executor.Context
- ): Iso[FilterState[Query, Candidate]] = {
- val broadcastStatsReceiver =
- Executor.broadcastStatsReceiver(context, filter.identifier, statsReceiver)
-
- val keptCounter = broadcastStatsReceiver.counter(Kept)
- val removedCounter = broadcastStatsReceiver.counter(Removed)
-
- val filterArrow = Arrow.flatMap[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- FilterExecutorIndividualResult[Candidate]
- ] {
- case (query, candidates) =>
- filter.apply(query, candidates).map { result =>
- FilterExecutorIndividualResult(
- identifier = filter.identifier,
- kept = result.kept,
- removed = result.removed)
- }
- }
-
- val observedArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- FilterExecutorIndividualResult[
- Candidate
- ]
- ] = wrapComponentWithExecutorBookkeeping(
- context = context,
- currentComponentIdentifier = filter.identifier,
- onSuccess = { result: FilterExecutorIndividualResult[Candidate] =>
- keptCounter.incr(result.kept.size)
- removedCounter.incr(result.removed.size)
- }
- )(
- filterArrow
- )
-
- val conditionallyRunArrow: Arrow[
- (Query, Seq[CandidateWithFeatures[Candidate]]),
- IndividualFilterResults[
- Candidate
- ]
- ] =
- filter match {
- case filter: Filter[Query, Candidate] with Conditionally[
- Filter.Input[Query, Candidate] @unchecked
- ] =>
- Arrow.ifelse(
- {
- case (query, candidates) =>
- filter.onlyIf(Filter.Input(query, candidates))
- },
- observedArrow,
- Arrow.value(ConditionalFilterDisabled(filter.identifier))
- )
- case _ => observedArrow
- }
-
- // return an `Iso` arrow for easier composition later
- Arrow
- .zipWithArg(
- Arrow
- .map[FilterState[Query, Candidate], (Query, Seq[CandidateWithFeatures[Candidate]])] {
- case FilterState(query, candidateToFeaturesMap, FilterExecutorResult(result, _)) =>
- (query, result.flatMap(candidateToFeaturesMap.get))
- }.andThen(conditionallyRunArrow))
- .map {
- case (
- FilterState(query, allCandidates, filterExecutorResult),
- filterResult: FilterExecutorIndividualResult[Candidate]) =>
- val resultWithCurrentPrepended =
- filterExecutorResult.individualFilterResults :+ filterResult
- val newFilterExecutorResult = FilterExecutorResult(
- result = filterResult.kept,
- individualFilterResults = resultWithCurrentPrepended)
- FilterState(query, allCandidates, newFilterExecutorResult)
-
- case (filterState, filterDisabledResult: ConditionalFilterDisabled) =>
- filterState.copy(
- executorResult = filterState.executorResult.copy(
- individualFilterResults =
- filterState.executorResult.individualFilterResults :+ filterDisabledResult
- ))
- }
- }
-}
-
-object FilterExecutor {
-
- /**
- * FilterState is an internal representation of the state that is passed between each individual filter arrow.
- *
- * @param query: The query
- * @param candidateToFeaturesMap: A lookup mapping from Candidate -> FilterCandidate, to rebuild the inputs quickly for the next filter
- * @param executorResult: The in-progress executor result
- */
- private case class FilterState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- query: Query,
- candidateToFeaturesMap: Map[Candidate, CandidateWithFeatures[Candidate]],
- executorResult: FilterExecutorResult[Candidate])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala
deleted file mode 100644
index bc0336620..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.twitter.product_mixer.core.service.filter_executor
-
-import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class FilterExecutorResult[Candidate](
- result: Seq[Candidate],
- individualFilterResults: Seq[IndividualFilterResults[Candidate]])
- extends ExecutorResult
-
-sealed trait IndividualFilterResults[+Candidate]
-case class ConditionalFilterDisabled(identifier: FilterIdentifier)
- extends IndividualFilterResults[Nothing]
-case class FilterExecutorIndividualResult[+Candidate](
- identifier: FilterIdentifier,
- kept: Seq[Candidate],
- removed: Seq[Candidate])
- extends IndividualFilterResults[Candidate]
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD
deleted file mode 100644
index 8b4ea4292..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala
deleted file mode 100644
index 32d4e4410..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.twitter.product_mixer.core.service.gate_executor
-
-import com.twitter.product_mixer.core.functional_component.gate.GateResult
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-
-case class ExecutedGateResult(identifier: GateIdentifier, result: GateResult)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala
deleted file mode 100644
index c1de292e8..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.twitter.product_mixer.core.service.gate_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.gate.BaseGate
-import com.twitter.product_mixer.core.functional_component.gate.GateResult
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Arrow.Iso
-import com.twitter.util.Return
-import com.twitter.util.Throw
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.immutable.Queue
-
-/**
- * A GateExecutor takes a Seq[Gate], executes them all sequentially, and
- * determines a final Continue or Stop decision.
- */
-@Singleton
-class GateExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor {
-
- private val Continue = "continue"
- private val Skipped = "skipped"
- private val Stop = "stop"
-
- def arrow[Query <: PipelineQuery](
- gates: Seq[BaseGate[Query]],
- context: Executor.Context
- ): Arrow[Query, GateExecutorResult] = {
-
- val gateArrows = gates.map(getIsoArrowForGate(_, context))
- val combinedArrow = isoArrowsSequentially(gateArrows)
-
- Arrow
- .map { query: Query => (query, GateExecutorResult(Queue.empty)) }
- .andThen(combinedArrow)
- .map {
- case (_, gateExecutorResult) =>
- // materialize the Queue into a List for faster future iterations
- GateExecutorResult(gateExecutorResult.individualGateResults.toList)
- }
- }
-
- /**
- * Each gate is transformed into a Iso Arrow over (Quest, List[GatewayResult]).
- *
- * This arrow:
- * - Adapts the input and output types of the underlying Gate arrow (an [[Iso[(Query, QueryResult)]])
- * - throws a [[StoppedGateException]] if [[GateResult.continue]] is false
- * - if its not false, prepends the current results to the [[GateExecutorResult.individualGateResults]] list
- */
- private def getIsoArrowForGate[Query <: PipelineQuery](
- gate: BaseGate[Query],
- context: Executor.Context
- ): Iso[(Query, GateExecutorResult)] = {
- val broadcastStatsReceiver =
- Executor.broadcastStatsReceiver(context, gate.identifier, statsReceiver)
-
- val continueCounter = broadcastStatsReceiver.counter(Continue)
- val skippedCounter = broadcastStatsReceiver.counter(Skipped)
- val stopCounter = broadcastStatsReceiver.counter(Stop)
-
- val observedArrow = wrapComponentWithExecutorBookkeeping(
- context,
- gate.identifier,
- onSuccess = { gateResult: GateResult =>
- gateResult match {
- case GateResult.Continue => continueCounter.incr()
- case GateResult.Skipped => skippedCounter.incr()
- case GateResult.Stop => stopCounter.incr()
- }
- }
- )(gate.arrow)
-
- val inputAdapted: Arrow[(Query, GateExecutorResult), GateResult] =
- Arrow
- .map[(Query, GateExecutorResult), Query] { case (query, _) => query }
- .andThen(observedArrow)
-
- val zipped = Arrow.zipWithArg(inputAdapted)
-
- // at each step, the current `GateExecutorResult.continue` value is correct for all already run gates
- val withStoppedGatesAsExceptions = zipped.map {
- case ((query, previousResults), currentResult) if currentResult.continue =>
- Return(
- (
- query,
- GateExecutorResult(
- previousResults.individualGateResults :+ ExecutedGateResult(
- gate.identifier,
- currentResult))
- ))
- case _ => Throw(StoppedGateException(gate.identifier))
- }.lowerFromTry
-
- /**
- * we gather stats before converting closed gates to exceptions because a closed gate
- * isn't a failure for the gate, its a normal behavior
- * but we do want to remap the the [[StoppedGateException]] created because the [[BaseGate]] is closed
- * to the correct [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure]],
- * so we remap with [[wrapWithErrorHandling]]
- */
- wrapWithErrorHandling(context, gate.identifier)(withStoppedGatesAsExceptions)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala
deleted file mode 100644
index 2a38cd59b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.service.gate_executor
-
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class GateExecutorResult(
- individualGateResults: Seq[ExecutedGateResult])
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala
deleted file mode 100644
index 7bd7bae29..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.service.gate_executor
-
-import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier
-
-import scala.util.control.NoStackTrace
-
-case class StoppedGateException(identifier: GateIdentifier)
- extends Exception("Closed gate stopped execution of the pipeline")
- with NoStackTrace {
- override def toString: String = s"StoppedGateException($identifier)"
-}
-
-object StoppedGateException {
-
- /**
- * Creates a [[PipelineFailureClassifier]] that is used as the default for classifying failures
- * in a pipeline by mapping [[StoppedGateException]] to a [[PipelineFailure]] with the provided
- * [[PipelineFailureCategory]]
- */
- def classifier(
- category: PipelineFailureCategory
- ): PipelineFailureClassifier = PipelineFailureClassifier {
- case stoppedGateException: StoppedGateException =>
- PipelineFailure(category, stoppedGateException.getMessage, Some(stoppedGateException))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD
deleted file mode 100644
index c34688181..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-core/src/main/scala",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala
deleted file mode 100644
index beb665c64..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.twitter.product_mixer.core.service.group_results_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder
-import com.twitter.product_mixer.core.model.common.CandidateWithFeatures
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PlatformIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition
-import com.twitter.product_mixer.core.model.common.presentation.CandidateSources
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation
-import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails
-import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation
-import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.immutable.ListSet
-
-// Most executors are in the core.service package, but this one is pipeline specific
-@Singleton
-class GroupResultsExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor {
-
- val identifier: ComponentIdentifier = PlatformIdentifier("GroupResults")
-
- def arrow[Candidate <: UniversalNoun[Any]](
- pipelineIdentifier: CandidatePipelineIdentifier,
- sourceIdentifier: CandidateSourceIdentifier,
- context: Executor.Context
- ): Arrow[GroupResultsExecutorInput[Candidate], GroupResultsExecutorResult] = {
-
- val groupArrow = Arrow.map { input: GroupResultsExecutorInput[Candidate] =>
- val modules: Map[Option[ModulePresentation], Seq[CandidateWithFeatures[Candidate]]] =
- input.candidates
- .map { candidate: CandidateWithFeatures[Candidate] =>
- val modulePresentationOpt: Option[ModulePresentation] =
- input.decorations.get(candidate.candidate).collect {
- case itemPresentation: ItemPresentation
- if itemPresentation.modulePresentation.isDefined =>
- itemPresentation.modulePresentation.get
- }
-
- (candidate, modulePresentationOpt)
- }.groupBy {
- case (_, modulePresentationOpt) => modulePresentationOpt
- }.mapValues {
- resultModuleOptTuples: Seq[
- (CandidateWithFeatures[Candidate], Option[ModulePresentation])
- ] =>
- resultModuleOptTuples.map {
- case (result, _) => result
- }
- }
-
- // Modules should be in their original order, but the groupBy above isn't stable.
- // Sort them by the sourcePosition, using the sourcePosition of their first contained
- // candidate.
- val sortedModules: Seq[(Option[ModulePresentation], Seq[CandidateWithFeatures[Candidate]])] =
- modules.toSeq
- .sortBy {
- case (_, results) =>
- results.headOption.map(_.features.get(CandidateSourcePosition))
- }
-
- val candidatesWithDetails: Seq[CandidateWithDetails] = sortedModules.flatMap {
- case (modulePresentationOpt, resultsSeq) =>
- val itemsWithDetails = resultsSeq.map { result =>
- val presentationOpt = input.decorations.get(result.candidate) match {
- case itemPresentation @ Some(_: ItemPresentation) => itemPresentation
- case _ => None
- }
-
- val baseFeatureMap = FeatureMapBuilder()
- .add(CandidatePipelines, ListSet.empty + pipelineIdentifier)
- .build()
-
- ItemCandidateWithDetails(
- candidate = result.candidate,
- presentation = presentationOpt,
- features = baseFeatureMap ++ result.features
- )
- }
-
- modulePresentationOpt
- .map { modulePresentation =>
- val moduleSourcePosition =
- resultsSeq.head.features.get(CandidateSourcePosition)
- val baseFeatureMap = FeatureMapBuilder()
- .add(CandidatePipelines, ListSet.empty + pipelineIdentifier)
- .add(CandidateSourcePosition, moduleSourcePosition)
- .add(CandidateSources, ListSet.empty + sourceIdentifier)
- .build()
-
- Seq(
- ModuleCandidateWithDetails(
- candidates = itemsWithDetails,
- presentation = Some(modulePresentation),
- features = baseFeatureMap
- ))
- }.getOrElse(itemsWithDetails)
- }
-
- GroupResultsExecutorResult(candidatesWithDetails)
- }
-
- wrapWithErrorHandling(context, identifier)(groupArrow)
- }
-}
-
-case class GroupResultsExecutorInput[Candidate <: UniversalNoun[Any]](
- candidates: Seq[CandidateWithFeatures[Candidate]],
- decorations: Map[UniversalNoun[Any], UniversalPresentation])
-
-case class GroupResultsExecutorResult(candidatesWithDetails: Seq[CandidateWithDetails])
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala
deleted file mode 100644
index af5ed42b9..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_execution_logger
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.inject.annotations.Flag
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.PipelineExecutionLoggerAllowList
-import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.util.FuturePools
-import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver
-import com.twitter.util.Try
-import com.twitter.util.logging.Logging
-import pprint.PPrinter
-import pprint.Tree
-import pprint.Util
-import pprint.tuplePrefix
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Initial implementation from:
- * https://stackoverflow.com/questions/15718506/scala-how-to-print-case-classes-like-pretty-printed-tree/57080463#57080463
- */
-object AllowListedPipelineExecutionLogger {
-
- /**
- * Given a case class who's arguments are all declared fields on the class,
- * returns an iterator of the field name and values
- */
- private[pipeline_execution_logger] def caseClassFields(
- caseClass: Product
- ): Iterator[(String, Any)] = {
- val fieldValues = caseClass.productIterator.toSet
- val fields = caseClass.getClass.getDeclaredFields.toSeq
- .filterNot(f => f.isSynthetic || java.lang.reflect.Modifier.isStatic(f.getModifiers))
- fields.iterator
- .map { f =>
- f.setAccessible(true)
- f.getName -> f.get(caseClass)
- }.filter { case (_, v) => fieldValues.contains(v) }
- }
-
- /**
- * Returns whether a given [[Product]] is a case class which we can render nicely which:
- * - has a [[Product.productArity]] <= the number of declared fields
- * - isn't a built in binary operator
- * - isn't a tuple
- * - who's arguments are fields (not methods)
- * - every [[Product.productElement]] has a corresponding field
- *
- * This will return false for some case classes where we can not reliably determine which field names correspond to
- * each value in the case class (this can happen if a case class implements an abstract class resulting in val fields
- * becoming methods.
- */
- private[pipeline_execution_logger] def isRenderableCaseClass(caseClass: Product): Boolean = {
- val possibleToBeRenderableCaseClass =
- caseClass.getClass.getDeclaredFields.length >= caseClass.productArity
- val isntBuiltInOperator =
- !(caseClass.productArity == 2 && Util.isOperator(caseClass.productPrefix))
- val isntTuple = !caseClass.getClass.getName.startsWith(tuplePrefix)
- val declaredFieldsMatchesCaseClassFields = {
- val caseClassFields = caseClass.productIterator.toSet
- caseClass.getClass.getDeclaredFields.iterator
- .filterNot(f => f.isSynthetic || java.lang.reflect.Modifier.isStatic(f.getModifiers))
- .count { f =>
- f.setAccessible(true)
- caseClassFields.contains(f.get(caseClass))
- } >= caseClass.productArity
- }
-
- possibleToBeRenderableCaseClass && isntBuiltInOperator && isntTuple && declaredFieldsMatchesCaseClassFields
- }
-
- /** Makes a [[Tree]] which will render as `key = value` */
- private def keyValuePair(key: String, value: Tree): Tree = {
- Tree.Infix(Tree.Literal(key), "=", value)
- }
-
- /**
- * Special handling for case classes who's field names can be easily paired with their values.
- * This will make the [[PPrinter]] render them as
- * {{{
- * CaseClassName(
- * field1 = value1,
- * field2 = value2
- * )
- * }}}
- * instead of
- * {{{
- * CaseClassName(
- * value1,
- * value2
- * )
- * }}}
- *
- * For case classes who's fields end up being compiled as methods, this will fall back
- * to the built in handling of case classes without their field names.
- */
- private[pipeline_execution_logger] def additionalHandlers: PartialFunction[Any, Tree] = {
- case caseClass: Product if isRenderableCaseClass(caseClass) =>
- Tree.Apply(
- caseClass.productPrefix,
- caseClassFields(caseClass).flatMap {
- case (key, value) =>
- val valueTree = printer.treeify(value, false, true)
- Seq(keyValuePair(key, valueTree))
- }
- )
- }
-
- /**
- * [[PPrinter]] instance to use when rendering scala objects
- * uses BlackAndWhite because colors mangle the output when looking at the logs in plain text
- */
- private val printer: PPrinter = PPrinter.BlackWhite.copy(
- // arbitrary high value to turn off truncation
- defaultHeight = Int.MaxValue,
- // the relatively high width will cause some wrapping but many of the pretty printed objects
- // will be sparse (e.g. None,\n None,\n, None,\n)
- defaultWidth = 300,
- // use reflection to print field names (can be deleted in Scala 2.13)
- additionalHandlers = additionalHandlers
- )
-
- /** Given any scala object, return a String representation of it */
- private[pipeline_execution_logger] def objectAsString(o: Any): String =
- printer.tokenize(o).mkString
-}
-
-@Singleton
-class AllowListedPipelineExecutionLogger @Inject() (
- @Flag(ServiceLocal) isServiceLocal: Boolean,
- @Flag(PipelineExecutionLoggerAllowList) allowList: Seq[String],
- statsReceiver: StatsReceiver)
- extends PipelineExecutionLogger
- with Logging {
-
- private val scopedStats = statsReceiver.scope("AllowListedPipelineExecutionLogger")
-
- val allowListRoles: Set[String] = allowList.toSet
-
- private val futurePool =
- FuturePools.boundedFixedThreadPool(
- "AllowListedPipelineExecutionLogger",
- // single thread, may need to be adjusted higher if it cant keep up with the work queue
- fixedThreadCount = 1,
- // arbitrarily large enough to handle spikes without causing large allocations or retaining past multiple GC cycles
- workQueueSize = 100,
- scopedStats
- )
-
- private val futureObserver = new FutureObserver[Unit](scopedStats, Seq.empty)
-
- private val loggerOutputPath = Try(System.getProperty("log.allow_listed_execution_logger.output"))
-
- override def apply(pipelineQuery: PipelineQuery, message: Any): Unit = {
-
- val userRoles: Set[String] = pipelineQuery.clientContext.userRoles.getOrElse(Set.empty)
-
- // Check if this request is in the allowlist via a cleverly optimized set intersection
- val allowListed =
- if (allowListRoles.size > userRoles.size)
- userRoles.exists(allowListRoles.contains)
- else
- allowListRoles.exists(userRoles.contains)
-
- if (isServiceLocal || allowListed) {
- futureObserver(
- /**
- * failure to enqueue the work will result with a failed [[com.twitter.util.Future]]
- * containing a [[java.util.concurrent.RejectedExecutionException]] which the wrapping [[futureObserver]]
- * will record metrics for.
- */
- futurePool {
- logger.info(AllowListedPipelineExecutionLogger.objectAsString(message))
-
- if (isServiceLocal && loggerOutputPath.isReturn) {
- println(s"Logged request to: ${loggerOutputPath.get()}")
- }
- }
- )
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD
deleted file mode 100644
index dffbcc694..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject",
- "3rdparty/jvm/com/lihaoyi:pprint",
- "3rdparty/jvm/net/codingwell:scala-guice",
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-core/src/main/scala/com/twitter/inject",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- ],
- exports = [
- "3rdparty/jvm/com/google/inject:guice",
- "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject",
- "3rdparty/jvm/com/lihaoyi:pprint",
- "3rdparty/jvm/net/codingwell:scala-guice",
- "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations",
- "finatra/inject/inject-core/src/main/scala",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala
deleted file mode 100644
index e6c7535c7..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_execution_logger
-
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-
-trait PipelineExecutionLogger {
- def apply(pipelineQuery: PipelineQuery, message: Any): Unit
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD
deleted file mode 100644
index fbc1b6b8c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD
+++ /dev/null
@@ -1,25 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala
deleted file mode 100644
index 511973cb1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.InvalidPipelineSelected
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-import com.twitter.util.logging.Logging
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * PipelineExecutor executes a single pipeline (of any type)
- * It does not currently support fail open/closed policies like CandidatePipelineExecutor does
- * In the future, maybe they can be merged.
- */
-
-case class PipelineExecutorRequest[Query](query: Query, pipelineIdentifier: ComponentIdentifier)
-
-@Singleton
-class PipelineExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor
- with Logging {
-
- def arrow[Query, ResultType](
- pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, ResultType]],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- context: Executor.Context
- ): Arrow[PipelineExecutorRequest[Query], PipelineExecutorResult[ResultType]] = {
-
- val wrappedPipelineArrowsByIdentifier = pipelineByIdentifier.mapValues { pipeline =>
- wrapPipelineWithExecutorBookkeeping(
- context,
- pipeline.identifier,
- qualityFactorObserverByPipeline.get(pipeline.identifier))(pipeline.arrow)
- }
-
- val appliedPipelineArrow = Arrow
- .identity[PipelineExecutorRequest[Query]]
- .map {
- case PipelineExecutorRequest(query, pipelineIdentifier) =>
- val pipeline = wrappedPipelineArrowsByIdentifier.getOrElse(
- pipelineIdentifier,
- // throwing instead of returning a `Throw(_)` and then `.lowerFromTry` because this is an exceptional case and we want to emphasize that by explicitly throwing
- // this case should never happen since this is checked in the `PipelineSelectorExecutor` but we check it anyway
- throw PipelineFailure(
- InvalidPipelineSelected,
- s"${context.componentStack.peek} attempted to execute $pipelineIdentifier",
- // the `componentStack` includes the missing pipeline so it can show up in metrics easier
- componentStack = Some(context.componentStack.push(pipelineIdentifier))
- )
- )
- (pipeline, query)
- }
- // less efficient than an `andThen` but since we dispatch this dynamically we need to use either `applyArrow` or `flatMap` and this is the better of those options
- .applyArrow
- .map(PipelineExecutorResult(_))
-
- // no additional error handling needed since we populate the component stack above already
- appliedPipelineArrow
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala
deleted file mode 100644
index 9953b4666..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_executor
-
-import com.twitter.product_mixer.core.pipeline.PipelineResult
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class PipelineExecutorResult[ResultType](
- pipelineResult: PipelineResult[ResultType])
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD
deleted file mode 100644
index 1aecf5960..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala
deleted file mode 100644
index 2506db301..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.side_effect.ExecuteSynchronously
-import com.twitter.product_mixer.core.functional_component.side_effect.FailOpen
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
-import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect.Inputs
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor._
-import com.twitter.stitch.Arrow
-import com.twitter.util.Return
-import com.twitter.util.Try
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PipelineResultSideEffectExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
- def arrow[Query <: PipelineQuery, MixerDomainResultType <: HasMarshalling](
- sideEffects: Seq[PipelineResultSideEffect[Query, MixerDomainResultType]],
- context: Executor.Context
- ): Arrow[Inputs[Query, MixerDomainResultType], PipelineResultSideEffectExecutor.Result] = {
-
- val individualArrows: Seq[
- Arrow[Inputs[Query, MixerDomainResultType], (SideEffectIdentifier, SideEffectResultType)]
- ] = sideEffects.map {
- case synchronousSideEffect: ExecuteSynchronously =>
- val failsRequestIfThrows = {
- wrapComponentWithExecutorBookkeeping(context, synchronousSideEffect.identifier)(
- Arrow.flatMap(synchronousSideEffect.apply))
- }
- synchronousSideEffect match {
- case failOpen: FailOpen =>
- // lift the failure
- failsRequestIfThrows.liftToTry.map(t =>
- (failOpen.identifier, SynchronousSideEffectResult(t)))
- case _ =>
- // don't encapsulate the failure
- failsRequestIfThrows.map(_ =>
- (synchronousSideEffect.identifier, SynchronousSideEffectResult(Return.Unit)))
- }
-
- case sideEffect =>
- Arrow
- .async(
- wrapComponentWithExecutorBookkeeping(context, sideEffect.identifier)(
- Arrow.flatMap(sideEffect.apply)))
- .andThen(Arrow.value((sideEffect.identifier, SideEffectResult)))
- }
-
- val conditionallyRunArrows = sideEffects.zip(individualArrows).map {
- case (
- sideEffect: Conditionally[
- PipelineResultSideEffect.Inputs[Query, MixerDomainResultType] @unchecked
- ],
- arrow) =>
- Arrow.ifelse[
- Inputs[Query, MixerDomainResultType],
- (SideEffectIdentifier, SideEffectResultType)](
- input => sideEffect.onlyIf(input),
- arrow,
- Arrow.value((sideEffect.identifier, TurnedOffByConditionally)))
- case (_, arrow) => arrow
- }
-
- Arrow
- .collect(conditionallyRunArrows)
- .map(results => Result(results))
- }
-}
-
-object PipelineResultSideEffectExecutor {
- case class Result(sideEffects: Seq[(SideEffectIdentifier, SideEffectResultType)])
- extends ExecutorResult
-
- sealed trait SideEffectResultType
-
- /** The [[PipelineResultSideEffect]] was executed asynchronously in a fire-and-forget way so no result will be available */
- case object SideEffectResult extends SideEffectResultType
-
- /** The result of the [[PipelineResultSideEffect]] that was executed with [[ExecuteSynchronously]] */
- case class SynchronousSideEffectResult(result: Try[Unit]) extends SideEffectResultType
-
- /** The result for when a [[PipelineResultSideEffect]] is turned off by [[Conditionally]]'s [[Conditionally.onlyIf]] */
- case object TurnedOffByConditionally extends SideEffectResultType
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD
deleted file mode 100644
index 7c5725005..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala
deleted file mode 100644
index bf211b63d..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_selector_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.util.logging.Logging
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PlatformIdentifier
-import com.twitter.product_mixer.core.pipeline.Pipeline
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.InvalidPipelineSelected
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class PipelineSelectorExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor
- with Logging {
-
- val identifier: ComponentIdentifier = PlatformIdentifier("PipelineSelector")
-
- def arrow[Query <: PipelineQuery, Response](
- pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]],
- pipelineSelector: Query => ComponentIdentifier,
- context: Executor.Context
- ): Arrow[Query, PipelineSelectorExecutorResult] = {
-
- val validateSelectedPipelineExists = Arrow
- .map(pipelineSelector)
- .map { chosenIdentifier =>
- if (pipelineByIdentifier.contains(chosenIdentifier)) {
- PipelineSelectorExecutorResult(chosenIdentifier)
- } else {
- // throwing instead of returning a `Throw(_)` and then `.lowerFromTry` because this is an exceptional case and we want to emphasize that by explicitly throwing
- throw PipelineFailure(
- InvalidPipelineSelected,
- s"${context.componentStack.peek} attempted to select $chosenIdentifier",
- // the `componentStack` includes the missing pipeline so it can show up in metrics easier
- componentStack = Some(context.componentStack.push(chosenIdentifier))
- )
- }
- }
-
- wrapWithErrorHandling(context, identifier)(validateSelectedPipelineExists)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala
deleted file mode 100644
index 3ffc8297f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.core.service.pipeline_selector_executor
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-
-case class PipelineSelectorExecutorResult(pipelineIdentifier: ComponentIdentifier)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD
deleted file mode 100644
index ae1c9b4fd..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala
deleted file mode 100644
index 43acb992f..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.twitter.product_mixer.core.service.quality_factor_executor
-
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-
-case class QualityFactorExecutorResult(
- pipelineQualityFactors: Map[ComponentIdentifier, Double])
-
-object QualityFactorExecutorResult {
- val empty: QualityFactorExecutorResult = QualityFactorExecutorResult(Map.empty)
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala
deleted file mode 100644
index b7a3e5819..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.twitter.product_mixer.core.service.query_feature_hydrator_executor
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.JsonSerializer
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.AsyncIndividualFeatureHydratorResult
-
-/** A [[JsonSerializer]] that skips the `Stitch` values */
-private[query_feature_hydrator_executor] class AsyncIndividualFeatureHydratorResultSerializer()
- extends JsonSerializer[AsyncIndividualFeatureHydratorResult] {
-
- override def serialize(
- asyncIndividualFeatureHydratorResult: AsyncIndividualFeatureHydratorResult,
- gen: JsonGenerator,
- serializers: SerializerProvider
- ): Unit =
- serializers.defaultSerializeValue(
- // implicitly calls `toString` on the identifier because they are keys in the Map
- Map(
- asyncIndividualFeatureHydratorResult.hydrateBefore ->
- asyncIndividualFeatureHydratorResult.features.map(_.toString)),
- gen
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD
deleted file mode 100644
index ffceb6261..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD
+++ /dev/null
@@ -1,28 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala
deleted file mode 100644
index 8d6e3c4c6..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala
+++ /dev/null
@@ -1,217 +0,0 @@
-package com.twitter.product_mixer.core.service.query_feature_hydrator_executor
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.Feature
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator
-import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator
-import com.twitter.product_mixer.core.model.common.Conditionally
-import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.Executor._
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.product_mixer.core.service.feature_hydrator_observer.FeatureHydratorObserver
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.AsyncIndividualFeatureHydratorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.BaseIndividualFeatureHydratorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.FeatureHydratorDisabled
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.IndividualFeatureHydratorResult
-import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.validateAsyncQueryFeatureHydrator
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class QueryFeatureHydratorExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
-
- def arrow[Query <: PipelineQuery](
- hydrators: Seq[BaseQueryFeatureHydrator[Query, _]],
- validPipelineSteps: Set[PipelineStepIdentifier],
- context: Executor.Context
- ): Arrow[Query, QueryFeatureHydratorExecutor.Result] = {
-
- val observer = new FeatureHydratorObserver(statsReceiver, hydrators, context)
- val hydratorsWithErrorHandling =
- hydrators.map { hydrator =>
- val queryFeatureHydratorArrow =
- getQueryHydratorArrow(hydrator, context, observer)
- val wrappedWithAsyncHandling =
- handleAsyncHydrator(hydrator, validPipelineSteps, queryFeatureHydratorArrow)
- handleConditionally(hydrator, wrappedWithAsyncHandling)
- }
-
- Arrow
- .collect(hydratorsWithErrorHandling)
- .map {
- results: Seq[
- (FeatureHydratorIdentifier, BaseIndividualFeatureHydratorResult)
- ] =>
- val combinedFeatureMap = FeatureMap.merge(results.collect {
- case (_, IndividualFeatureHydratorResult(featureMap)) => featureMap
- })
-
- val asyncFeatureMaps = results.collect {
- case (
- hydratorIdentifier,
- AsyncIndividualFeatureHydratorResult(hydrateBefore, featuresToHydrate, ref)) =>
- (hydratorIdentifier, hydrateBefore, featuresToHydrate, ref)
- }
-
- QueryFeatureHydratorExecutor.Result(
- individualFeatureMaps = results.toMap,
- featureMap = combinedFeatureMap,
- asyncFeatureMap = AsyncFeatureMap.fromFeatureMaps(asyncFeatureMaps)
- )
- }
- }
-
- def handleConditionally[Query <: PipelineQuery](
- hydrator: BaseQueryFeatureHydrator[Query, _],
- arrow: Arrow[
- Query,
- BaseIndividualFeatureHydratorResult
- ]
- ): Arrow[
- Query,
- (FeatureHydratorIdentifier, BaseIndividualFeatureHydratorResult)
- ] = {
- val conditionallyRunArrow = hydrator match {
- case hydrator: BaseQueryFeatureHydrator[Query, _] with Conditionally[Query @unchecked] =>
- Arrow.ifelse[Query, BaseIndividualFeatureHydratorResult](
- hydrator.onlyIf,
- arrow,
- Arrow.value(FeatureHydratorDisabled)
- )
- case _ => arrow
- }
-
- Arrow.join(
- Arrow.value(hydrator.identifier),
- conditionallyRunArrow
- )
- }
-
- def handleAsyncHydrator[Query <: PipelineQuery](
- hydrator: BaseQueryFeatureHydrator[Query, _],
- validPipelineSteps: Set[PipelineStepIdentifier],
- arrow: Arrow[
- Query,
- IndividualFeatureHydratorResult
- ]
- ): Arrow[Query, BaseIndividualFeatureHydratorResult] = {
- hydrator match {
- case hydrator: BaseQueryFeatureHydrator[
- Query,
- _
- ] with AsyncHydrator =>
- validateAsyncQueryFeatureHydrator(hydrator, validPipelineSteps)
-
- startArrowAsync(arrow.map(_.featureMap))
- .map { ref =>
- AsyncIndividualFeatureHydratorResult(
- hydrator.hydrateBefore,
- hydrator.features.asInstanceOf[Set[Feature[_, _]]],
- ref
- )
- }
-
- case _ => arrow
- }
- }
-
- def getQueryHydratorArrow[Query <: PipelineQuery](
- hydrator: BaseQueryFeatureHydrator[Query, _],
- context: Executor.Context,
- queryFeatureHydratorObserver: FeatureHydratorObserver
- ): Arrow[Query, IndividualFeatureHydratorResult] = {
-
- val componentExecutorContext = context.pushToComponentStack(hydrator.identifier)
- val hydratorArrow: Arrow[Query, FeatureMap] =
- Arrow.flatMap { query: Query => hydrator.hydrate(query) }
-
- val validationFn: FeatureMap => FeatureMap = hydrator match {
- // Feature store query hydrators store the resulting PredictionRecord and not
- // the features, so we cannot validate the same way
- case _: FeatureStoreV1QueryFeatureHydrator[Query] =>
- identity
- case _ =>
- validateFeatureMap(
- hydrator.features.asInstanceOf[Set[Feature[_, _]]],
- _,
- componentExecutorContext)
- }
-
- // record the component-level stats
- val observedArrow =
- wrapComponentWithExecutorBookkeeping[Query, FeatureMap](
- context,
- hydrator.identifier
- )(hydratorArrow.map(validationFn))
-
- // store non-configuration errors in the FeatureMap
- val liftNonValidationFailuresToFailedFeatures = Arrow.handle[FeatureMap, FeatureMap] {
- case NotAMisconfiguredFeatureMapFailure(e) =>
- featureMapWithFailuresForFeatures(
- hydrator.features.asInstanceOf[Set[Feature[_, _]]],
- e,
- componentExecutorContext)
- }
-
- val observedLiftedAndWrapped = observedArrow
- .andThen(liftNonValidationFailuresToFailedFeatures)
- .applyEffect(Arrow.map[FeatureMap, Unit](featureMap =>
- // record per-feature stats, this is separate from the component stats handled by `wrapWithExecutorBookkeeping`
- queryFeatureHydratorObserver.observeFeatureSuccessAndFailures(hydrator, Seq(featureMap))))
- .map(IndividualFeatureHydratorResult)
-
- observedLiftedAndWrapped
- }
-}
-
-object QueryFeatureHydratorExecutor {
- case class Result(
- individualFeatureMaps: Map[
- FeatureHydratorIdentifier,
- BaseIndividualFeatureHydratorResult
- ],
- featureMap: FeatureMap,
- asyncFeatureMap: AsyncFeatureMap)
- extends ExecutorResult
-
- sealed trait BaseIndividualFeatureHydratorResult
-
- case object FeatureHydratorDisabled extends BaseIndividualFeatureHydratorResult
- case class IndividualFeatureHydratorResult(featureMap: FeatureMap)
- extends BaseIndividualFeatureHydratorResult
-
- /** Async result, serializes without the [[Stitch]] field since it's not serializable */
- @JsonSerialize(using = classOf[AsyncIndividualFeatureHydratorResultSerializer])
- case class AsyncIndividualFeatureHydratorResult(
- hydrateBefore: PipelineStepIdentifier,
- features: Set[Feature[_, _]],
- ref: Stitch[FeatureMap])
- extends BaseIndividualFeatureHydratorResult
-
- /**
- * Validates whether the [[AsyncHydrator.hydrateBefore]] [[PipelineStepIdentifier]] is valid
- *
- * @param asyncQueryFeatureHydrator the hydrator to validate
- * @param validPipelineSteps a Set of [[PipelineStepIdentifier]]s which are valid places to populate async
- * [[Feature]]s in a [[com.twitter.product_mixer.core.pipeline.Pipeline]]
- */
- def validateAsyncQueryFeatureHydrator(
- asyncQueryFeatureHydrator: AsyncHydrator,
- validPipelineSteps: Set[PipelineStepIdentifier]
- ): Unit =
- require(
- validPipelineSteps.contains(asyncQueryFeatureHydrator.hydrateBefore),
- s"`AsyncHydrator.hydrateBefore` contained ${asyncQueryFeatureHydrator.hydrateBefore} which was not in the parent pipeline's " +
- s"`PipelineConfig` Companion object field `stepsAsyncFeatureHydrationCanBeCompletedBy = $validPipelineSteps`."
- )
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD
deleted file mode 100644
index 2b03f2775..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala
deleted file mode 100644
index 47b3a762a..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala
+++ /dev/null
@@ -1,172 +0,0 @@
-package com.twitter.product_mixer.core.service.scoring_pipeline_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.feature.featuremap.FeatureMap
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier
-import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.FailOpenPolicy
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineResult
-import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor.ScoringPipelineState
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Arrow.Iso
-import com.twitter.util.logging.Logging
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.collection.immutable.Queue
-
-@Singleton
-class ScoringPipelineExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor
- with Logging {
- def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- pipelines: Seq[ScoringPipeline[Query, Candidate]],
- context: Executor.Context,
- defaultFailOpenPolicy: FailOpenPolicy,
- failOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy],
- qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver],
- ): Arrow[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[Candidate]] = {
- val scoringPipelineArrows = pipelines.map { pipeline =>
- val failOpenPolicy = failOpenPolicies.getOrElse(pipeline.identifier, defaultFailOpenPolicy)
- val qualityFactorObserver = qualityFactorObserverByPipeline.get(pipeline.identifier)
-
- getIsoArrowForScoringPipeline(
- pipeline,
- context,
- failOpenPolicy,
- qualityFactorObserver
- )
- }
- val combinedArrow = isoArrowsSequentially(scoringPipelineArrows)
- Arrow
- .map[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineState[Query, Candidate]] {
- case input =>
- ScoringPipelineState(
- input.query,
- input.itemCandidatesWithDetails,
- ScoringPipelineExecutorResult(input.itemCandidatesWithDetails, Queue.empty))
- }.flatMapArrow(combinedArrow).map { state =>
- state.executorResult.copy(individualPipelineResults =
- // materialize the Queue into a List for faster future iterations
- state.executorResult.individualPipelineResults.toList)
- }
- }
-
- private def getIsoArrowForScoringPipeline[
- Query <: PipelineQuery,
- Candidate <: UniversalNoun[Any]
- ](
- pipeline: ScoringPipeline[Query, Candidate],
- context: Executor.Context,
- failOpenPolicy: FailOpenPolicy,
- qualityFactorObserver: Option[QualityFactorObserver]
- ): Iso[ScoringPipelineState[Query, Candidate]] = {
- val pipelineArrow = Arrow
- .map[ScoringPipelineState[Query, Candidate], ScoringPipeline.Inputs[Query]] { state =>
- ScoringPipeline.Inputs(state.query, state.allCandidates)
- }.flatMapArrow(pipeline.arrow)
-
- val observedArrow = wrapPipelineWithExecutorBookkeeping(
- context,
- pipeline.identifier,
- qualityFactorObserver,
- failOpenPolicy)(pipelineArrow)
-
- Arrow
- .zipWithArg(
- observedArrow
- ).map {
- case (
- scoringPipelinesState: ScoringPipelineState[Query, Candidate],
- scoringPipelineResult: ScoringPipelineResult[Candidate]) =>
- val updatedCandidates: Seq[ItemCandidateWithDetails] =
- mkUpdatedCandidates(pipeline.identifier, scoringPipelinesState, scoringPipelineResult)
- ScoringPipelineState(
- scoringPipelinesState.query,
- updatedCandidates,
- scoringPipelinesState.executorResult
- .copy(
- updatedCandidates,
- scoringPipelinesState.executorResult.individualPipelineResults :+ scoringPipelineResult)
- )
- }
- }
-
- private def mkUpdatedCandidates[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- scoringPipelineIdentifier: ScoringPipelineIdentifier,
- scoringPipelinesState: ScoringPipelineState[Query, Candidate],
- scoringPipelineResult: ScoringPipelineResult[Candidate]
- ): Seq[ItemCandidateWithDetails] = {
- if (scoringPipelineResult.failure.isEmpty) {
-
- /**
- * It's important that we map back from which actual item candidate was scored by looking
- * at the selector results. This is to defend against the same candidate being selected
- * from two different candidate pipelines. If one is selected and the other isn't, we
- * should only score the selected one. If both are selected and each is scored differently
- * we should get the right score for each.
- */
- val selectedItemCandidates: Seq[ItemCandidateWithDetails] =
- scoringPipelineResult.selectorResults
- .getOrElse(throw PipelineFailure(
- IllegalStateFailure,
- s"Missing Selector Results in Scoring Pipeline $scoringPipelineIdentifier")).selectedCandidates.collect {
- case itemCandidateWithDetails: ItemCandidateWithDetails =>
- itemCandidateWithDetails
- }
- val scoredFeatureMaps: Seq[FeatureMap] = scoringPipelineResult.result
- .getOrElse(Seq.empty).map(_.features)
-
- if (scoredFeatureMaps.isEmpty) {
- // It's possible that all Scorers are [[Conditionally]] off. In this case, we return empty
- // and don't validate the list size since this is done in the hydrator/scorer executor.
- scoringPipelinesState.allCandidates
- } else if (selectedItemCandidates.length != scoredFeatureMaps.length) {
- // The length of the inputted candidates should always match the returned feature map, unless
- throw PipelineFailure(
- IllegalStateFailure,
- s"Missing configured scorer result, length of scorer results does not match the length of selected candidates")
- } else {
- /* Zip the selected item candidate seq back to the scored feature maps, this works
- * because the scored results will always have the same number of elements returned
- * and it should match the same order. We then loop through all candidates because the
- * expectation is to always keep the result since a subsequent scoring pipeline can score a
- * candidate that the current one did not. We only update the feature map of the candidate
- * if it was selected and scored.
- */
- val selectedItemCandidateToScorerMap: Map[ItemCandidateWithDetails, FeatureMap] =
- selectedItemCandidates.zip(scoredFeatureMaps).toMap
- scoringPipelinesState.allCandidates.map { itemCandidateWithDetails =>
- selectedItemCandidateToScorerMap.get(itemCandidateWithDetails) match {
- case Some(scorerResult) =>
- itemCandidateWithDetails.copy(features =
- itemCandidateWithDetails.features ++ scorerResult)
- case None => itemCandidateWithDetails
- }
- }
- }
- } else {
- // If the underlying scoring pipeline has failed open, just keep the existing candidates
- scoringPipelinesState.allCandidates
- }
- }
-}
-
-object ScoringPipelineExecutor {
- private case class ScoringPipelineState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]](
- query: Query,
- allCandidates: Seq[ItemCandidateWithDetails],
- executorResult: ScoringPipelineExecutorResult[Candidate])
-
- case class Inputs[Query <: PipelineQuery](
- query: Query,
- itemCandidatesWithDetails: Seq[ItemCandidateWithDetails])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala
deleted file mode 100644
index a018be70c..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.twitter.product_mixer.core.service.scoring_pipeline_executor
-
-import com.twitter.product_mixer.core.model.common.UniversalNoun
-import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineResult
-
-case class ScoringPipelineExecutorResult[Candidate <: UniversalNoun[Any]](
- result: Seq[ItemCandidateWithDetails],
- individualPipelineResults: Seq[ScoringPipelineResult[Candidate]])
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD
deleted file mode 100644
index 34a1ddc21..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD
+++ /dev/null
@@ -1,26 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala
deleted file mode 100644
index ba9b946a0..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.twitter.product_mixer.core.service.selector_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.selector.Selector
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.identifier.SelectorIdentifier
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.pipeline.PipelineQuery
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Applies a `Seq[Selector]` in sequential order.
- * Returns the results, and also a detailed list each selector's results (for debugging / understandability).
- */
-@Singleton
-class SelectorExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor {
- def arrow[Query <: PipelineQuery](
- selectors: Seq[Selector[Query]],
- context: Executor.Context
- ): Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = {
-
- if (selectors.isEmpty) {
- throw PipelineFailure(
- IllegalStateFailure,
- "Must provide a non-empty Seq of Selectors. Check the config indicated by the componentStack and ensure that a non-empty Selector Seq is provided.",
- componentStack = Some(context.componentStack)
- )
- }
-
- val selectorArrows =
- selectors.zipWithIndex.foldLeft(Arrow.identity[(Query, IndexedSeq[SelectorResult])]) {
- case (previousSelectorArrows, (selector, index)) =>
- val selectorResult = getIndividualSelectorIsoArrow(selector, index, context)
- previousSelectorArrows.andThen(selectorResult)
- }
-
- Arrow
- .zipWithArg(
- Arrow
- .map[SelectorExecutor.Inputs[Query], (Query, IndexedSeq[SelectorResult])] {
- case SelectorExecutor.Inputs(query, candidates) =>
- (query, IndexedSeq(SelectorResult(candidates, Seq.empty)))
- }.andThen(selectorArrows)).map {
- case (inputs, (_, selectorResults)) =>
- // the last results, safe because it's always non-empty since it starts with 1 element in it
- val SelectorResult(remainingCandidates, result) = selectorResults.last
-
- val resultsAndRemainingCandidates =
- (result.iterator ++ remainingCandidates.iterator).toSet
-
- // the droppedCandidates are all the candidates which are in neither the result or remainingCandidates
- val droppedCandidates = inputs.candidatesWithDetails.iterator
- .filterNot(resultsAndRemainingCandidates.contains)
- .toIndexedSeq
-
- SelectorExecutorResult(
- selectedCandidates = result,
- remainingCandidates = remainingCandidates,
- droppedCandidates = droppedCandidates,
- individualSelectorResults =
- selectorResults.tail // `.tail` to remove the initial state we had
- )
- }
- }
-
- private def getIndividualSelectorIsoArrow[Query <: PipelineQuery](
- selector: Selector[Query],
- index: Int,
- context: Executor.Context
- ): Arrow.Iso[(Query, IndexedSeq[SelectorResult])] = {
- val identifier = SelectorIdentifier(selector.getClass.getSimpleName, index)
-
- val arrow = Arrow
- .identity[(Query, IndexedSeq[SelectorResult])]
- .map {
- case (query, previousResults) =>
- // last is safe here because we pass in a non-empty IndexedSeq
- val previousResult = previousResults.last
- val currentResult = selector.apply(
- query,
- previousResult.remainingCandidates,
- previousResult.result
- )
- (query, previousResults :+ currentResult)
- }
-
- wrapComponentsWithTracingOnly(context, identifier)(
- wrapWithErrorHandling(context, identifier)(
- arrow
- )
- )
- }
-}
-
-object SelectorExecutor {
- case class Inputs[Query <: PipelineQuery](
- query: Query,
- candidatesWithDetails: Seq[CandidateWithDetails])
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala
deleted file mode 100644
index 8b6038feb..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.twitter.product_mixer.core.service.selector_executor
-
-import com.twitter.product_mixer.core.functional_component.selector.SelectorResult
-import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails
-import com.twitter.product_mixer.core.service.ExecutorResult
-
-case class SelectorExecutorResult(
- selectedCandidates: Seq[CandidateWithDetails],
- remainingCandidates: Seq[CandidateWithDetails],
- droppedCandidates: Seq[CandidateWithDetails],
- individualSelectorResults: Seq[SelectorResult])
- extends ExecutorResult
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD
deleted file mode 100644
index 4cb8369e2..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "stitch/stitch-core",
- "strato/config/src/thrift/com/twitter/strato/graphql:api-media-graphql-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala",
- "strato/config/src/thrift/com/twitter/strato/graphql:topics-graphql-scala",
- "util/util-core:scala",
- ],
- exports = [
- "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala
deleted file mode 100644
index 0dbda7321..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.twitter.product_mixer.core.service.slice
-
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest
-import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry
-import com.twitter.stitch.Stitch
-import com.twitter.strato.graphql.thriftscala.SliceResult
-import com.twitter.timelines.configapi.Params
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.reflect.runtime.universe.TypeTag
-
-/**
- * Look up and execute Slice products in the [[ProductPipelineRegistry]]
- */
-@Singleton
-class SliceService @Inject() (productPipelineRegistry: ProductPipelineRegistry) {
-
- def getSliceResponse[RequestType <: Request](
- request: RequestType,
- params: Params
- )(
- implicit requestTypeTag: TypeTag[RequestType]
- ): Stitch[SliceResult] =
- productPipelineRegistry
- .getProductPipeline[RequestType, SliceResult](request.product)
- .process(ProductPipelineRequest(request, params))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD
deleted file mode 100644
index 2e7568b01..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala
deleted file mode 100644
index 19a3ed126..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.twitter.product_mixer.core.service.transformer_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.transformer.Transformer
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-import com.twitter.util.Try
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * For wrapping [[Transformer]]s that are applied per-candidate
- *
- * Records a single span for running all the components,
- * but stats per-component.
- */
-@Singleton
-class PerCandidateTransformerExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
-
- def arrow[In, Out](
- transformer: Transformer[In, Out],
- context: Executor.Context,
- ): Arrow[Seq[In], Seq[Try[Out]]] = {
- val perCandidateArrow = wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing(
- context,
- transformer.identifier
- )(Arrow.map(transformer.transform)).liftToTry
-
- wrapComponentsWithTracingOnly(
- context,
- transformer.identifier
- )(Arrow.sequence(perCandidateArrow))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala
deleted file mode 100644
index bdefad6f3..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.twitter.product_mixer.core.service.transformer_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.transformer.Transformer
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.stitch.Arrow
-
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TransformerExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor {
- def arrow[In, Out](
- transformer: Transformer[In, Out],
- context: Executor.Context
- ): Arrow[In, Out] = {
- wrapComponentWithExecutorBookkeeping(
- context,
- transformer.identifier
- )(Arrow.map(transformer.transform))
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD
deleted file mode 100644
index 7cedc62ae..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
- exports = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service",
- "stitch/stitch-core",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala
deleted file mode 100644
index c93c9000e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.twitter.product_mixer.core.service.transport_marshaller_executor
-
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller
-import com.twitter.product_mixer.core.model.marshalling.HasMarshalling
-import com.twitter.product_mixer.core.service.Executor
-import com.twitter.product_mixer.core.service.ExecutorResult
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor.Inputs
-import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor.Result
-import com.twitter.stitch.Arrow
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Executes a [[TransportMarshaller]].
- *
- * @note This is a synchronous transform, so we don't observe it directly. Failures and such
- * can be observed at the parent pipeline.
- */
-@Singleton
-class TransportMarshallerExecutor @Inject() (override val statsReceiver: StatsReceiver)
- extends Executor {
-
- def arrow[DomainResponseType <: HasMarshalling, TransportResponseType](
- marshaller: TransportMarshaller[DomainResponseType, TransportResponseType],
- context: Executor.Context
- ): Arrow[Inputs[DomainResponseType], Result[TransportResponseType]] = {
- val arrow =
- Arrow.map[Inputs[DomainResponseType], Result[TransportResponseType]] {
- case Inputs(domainResponse) => Result(marshaller(domainResponse))
- }
-
- wrapComponentWithExecutorBookkeeping(context, marshaller.identifier)(arrow)
- }
-}
-
-object TransportMarshallerExecutor {
- case class Inputs[DomainResponseType <: HasMarshalling](domainResponse: DomainResponseType)
- case class Result[TransportResponseType](result: TransportResponseType) extends ExecutorResult
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD
deleted file mode 100644
index 1f4780222..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/com/lihaoyi:pprint",
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "stitch/stitch-core",
- "util/util-core:scala",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala
deleted file mode 100644
index 0e08f670e..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.twitter.product_mixer.core.service.urp
-
-import com.twitter.pages.render.{thriftscala => urp}
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest
-import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Params
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.reflect.runtime.universe.TypeTag
-
-@Singleton
-class UrpService @Inject() (productPipelineRegistry: ProductPipelineRegistry) {
-
- def getUrpResponse[RequestType <: Request](
- request: RequestType,
- params: Params
- )(
- implicit requestTypeTag: TypeTag[RequestType]
- ): Stitch[urp.Page] =
- productPipelineRegistry
- .getProductPipeline[RequestType, urp.Page](request.product)
- .process(ProductPipelineRequest(request, params))
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD
deleted file mode 100644
index b4c6c49a1..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD
+++ /dev/null
@@ -1,20 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "3rdparty/jvm/javax/inject:javax.inject",
- "configapi/configapi-core",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry",
- "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala",
- "stitch/stitch-core",
- "util/util-core:scala",
- "util/util-jackson/src/main/scala/com/twitter/util/jackson",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala
deleted file mode 100644
index 2f8c79d60..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.twitter.product_mixer.core.service.urt
-
-import com.fasterxml.jackson.databind.SerializationFeature
-import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.UrtTransportMarshaller
-import com.twitter.product_mixer.core.model.marshalling.request.Request
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
-import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled
-import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest
-import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry
-import com.twitter.product_mixer.core.{thriftscala => t}
-import com.twitter.stitch.Stitch
-import com.twitter.timelines.configapi.Params
-import com.twitter.timelines.render.{thriftscala => urt}
-import com.twitter.util.jackson.ScalaObjectMapper
-
-import javax.inject.Inject
-import javax.inject.Singleton
-import scala.reflect.runtime.universe.TypeTag
-
-/**
- * Look up and execute products in the [[ProductPipelineRegistry]]
- */
-@Singleton
-class UrtService @Inject() (productPipelineRegistry: ProductPipelineRegistry) {
-
- def getUrtResponse[RequestType <: Request](
- request: RequestType,
- params: Params
- )(
- implicit requestTypeTag: TypeTag[RequestType]
- ): Stitch[urt.TimelineResponse] =
- productPipelineRegistry
- .getProductPipeline[RequestType, urt.TimelineResponse](request.product)
- .process(ProductPipelineRequest(request, params))
- .handle {
- // Detect ProductDisabled and convert it to TimelineUnavailable
- case pipelineFailure: PipelineFailure if pipelineFailure.category == ProductDisabled =>
- UrtTransportMarshaller.unavailable("")
- }
-
- /**
- * Get detailed pipeline execution as a serialized JSON String
- */
- def getPipelineExecutionResult[RequestType <: Request](
- request: RequestType,
- params: Params
- )(
- implicit requestTypeTag: TypeTag[RequestType]
- ): Stitch[t.PipelineExecutionResult] =
- productPipelineRegistry
- .getProductPipeline[RequestType, urt.TimelineResponse](request.product)
- .arrow(ProductPipelineRequest(request, params)).map { detailedResult =>
- val mapper = ScalaObjectMapper()
- // configure so that exception is not thrown whenever case class is not serializable
- mapper.underlying.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
- val serializedJSON = mapper.writePrettyString(detailedResult)
- t.PipelineExecutionResult(serializedJSON)
- }
-
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD
deleted file mode 100644
index 14035e637..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-core/src/main",
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "servo/util",
- "snowflake:id",
- "stitch/stitch-core",
- "util/util-core:util-core-util",
- "util/util-stats",
- ],
- exports = [
- "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure",
- "servo/util",
- "snowflake:id",
- "stitch/stitch-core",
- "util/util-core:util-core-util",
- "util/util-stats",
- ],
-)
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala
deleted file mode 100644
index 52885db34..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.twitter.product_mixer.core.util
-
-import com.twitter.concurrent.NamedPoolThreadFactory
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.util.Duration
-import com.twitter.util.FuturePool
-
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import java.util.concurrent.LinkedBlockingQueue
-import java.util.concurrent.ThreadPoolExecutor
-import java.util.concurrent.TimeUnit
-
-/**
- * Utility for making [[FuturePool]] with finite thread counts and different work queue options
- * while also monitoring the size of the work queue that's used.
- *
- * This only handles the cases where the number of threads are bounded.
- * For unbounded numbers of threads in a [[FuturePool]] use [[FuturePool.interruptibleUnboundedPool]] instead.
- */
-object FuturePools {
-
- /**
- * Makes a [[FuturePool]] with a fixed number of threads and a work queue
- * with a maximum size of `maxWorkQueueSize`.
- *
- * @note the [[FuturePool]] returns a failed [[com.twitter.util.Future]]s containing
- * [[java.util.concurrent.RejectedExecutionException]] when trying to enqueue
- * work when the work queue is full.
- */
- def boundedFixedThreadPool(
- name: String,
- fixedThreadCount: Int,
- workQueueSize: Int,
- statsReceiver: StatsReceiver
- ): FuturePool =
- futurePool(
- name = name,
- minThreads = fixedThreadCount,
- maxThreads = fixedThreadCount,
- keepIdleThreadsAlive = Duration.Zero,
- workQueue = new ArrayBlockingQueue[Runnable](workQueueSize),
- statsReceiver = statsReceiver
- )
-
- /**
- * Makes a [[FuturePool]] with a fix number of threads and an unbounded work queue
- *
- * @note Since the work queue is unbounded, this will fill up memory if the available worker threads can't keep up
- */
- def unboundedFixedThreadPool(
- name: String,
- fixedThreadCount: Int,
- statsReceiver: StatsReceiver
- ): FuturePool =
- futurePool(
- name = name,
- minThreads = fixedThreadCount,
- maxThreads = fixedThreadCount,
- keepIdleThreadsAlive = Duration.Zero,
- workQueue = new LinkedBlockingQueue[Runnable],
- statsReceiver = statsReceiver
- )
-
- /**
- * Makes a [[FuturePool]] with the provided thread configuration and
- * who's `workQueue` is monitored by a [[com.twitter.finagle.stats.Gauge]]
- *
- * @note if `minThreads` == `maxThreads` then the threadpool has a fixed size
- *
- * @param name name of the threadpool
- * @param minThreads minimum number of threads in the pool
- * @param maxThreads maximum number of threads in the pool
- * @param keepIdleThreadsAlive threads that are idle for this long will be removed from
- * the pool if there are more than `minThreads` in the pool.
- * If the pool size is fixed this is ignored.
- */
- private def futurePool(
- name: String,
- minThreads: Int,
- maxThreads: Int,
- keepIdleThreadsAlive: Duration,
- workQueue: BlockingQueue[Runnable],
- statsReceiver: StatsReceiver
- ): FuturePool = {
- val gaugeReference = statsReceiver.addGauge("workQueueSize")(workQueue.size())
-
- val threadFactory = new NamedPoolThreadFactory(name, makeDaemons = true)
-
- val executorService =
- new ThreadPoolExecutor(
- minThreads,
- maxThreads, // ignored by ThreadPoolExecutor when an unbounded queue is provided
- keepIdleThreadsAlive.inMillis,
- TimeUnit.MILLISECONDS,
- workQueue,
- threadFactory)
-
- FuturePool.interruptible(executorService)
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala
deleted file mode 100644
index cb0a92657..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.twitter.product_mixer.core.util
-
-import com.twitter.finagle.offload.OffloadFuturePool
-import com.twitter.util.Future
-
-object OffloadFuturePools {
-
- def parallelize[In, Out](
- inputSeq: Seq[In],
- transformer: In => Out,
- parallelism: Int
- ): Future[Seq[Out]] = {
- parallelize(inputSeq, transformer.andThen(Some(_)), parallelism, None).map(_.flatten)
- }
-
- def parallelize[In, Out](
- inputSeq: Seq[In],
- transformer: In => Out,
- parallelism: Int,
- default: Out
- ): Future[Seq[Out]] = {
- val threadProcessFutures = (0 until parallelism).map { i =>
- OffloadFuturePool.getPool(partitionAndProcessInput(inputSeq, transformer, i, parallelism))
- }
-
- val resultMap = Future.collect(threadProcessFutures).map(_.flatten.toMap)
-
- Future.collect {
- inputSeq.indices.map { idx =>
- resultMap.map(_.getOrElse(idx, default))
- }
- }
- }
-
- private def partitionAndProcessInput[In, Out](
- inputSeq: Seq[In],
- transformer: In => Out,
- threadId: Int,
- parallelism: Int
- ): Seq[(Int, Out)] = {
- partitionInputForThread(inputSeq, threadId, parallelism)
- .map {
- case (inputRecord, idx) =>
- (idx, transformer(inputRecord))
- }
- }
-
- private def partitionInputForThread[In](
- inputSeq: Seq[In],
- threadId: Int,
- parallelism: Int
- ): Seq[(In, Int)] = {
- inputSeq.zipWithIndex
- .filter {
- case (_, idx) => idx % parallelism == threadId
- case _ => false
- }
- }
-}
diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala
deleted file mode 100644
index eb55b231b..000000000
--- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.twitter.product_mixer.core.util
-
-import com.twitter.snowflake.id.SnowflakeId
-import com.twitter.util.Time
-
-object SortIndexBuilder {
-
- /** the [[Time]] from a [[SnowflakeId]] */
- def idToTime(id: Long): Time =
- Time.fromMilliseconds(SnowflakeId.unixTimeMillisOrFloorFromId(id))
-
- /** the first [[SnowflakeId]] possible for a given [[Time]] */
- def timeToId(time: Time): Long = SnowflakeId.firstIdFor(time)
-
- /** the first [[SnowflakeId]] possible for a given unix epoch millis */
- def timeToId(timeMillis: Long): Long = SnowflakeId.firstIdFor(timeMillis)
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD
deleted file mode 100644
index 2be84e6a8..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-core/src/main",
- "finagle/finagle-http/src/main/scala",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "util/util-core",
- ],
- exports = [
- "finagle/finagle-core/src/main",
- "finagle/finagle-http/src/main/scala",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala
deleted file mode 100644
index fd203cacf..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.twitter.product_mixer.shared_library.http_client
-
-import com.twitter.finagle.Http
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.mtls.client.MtlsStackClient._
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.util.Duration
-
-object FinagleHttpClientBuilder {
-
- /**
- * Build a Finagle HTTP client with S2S Auth / Mutual TLS
- *
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP Client with S2S Auth / Mutual TLS
- */
- def buildFinagleHttpClientMutualTls(
- requestTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver
- ): Http.Client =
- buildFinagleHttpClient(
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- statsReceiver = statsReceiver
- ).withMutualTls(serviceIdentifier)
-
- /**
- * Build a Finagle HTTP client
- *
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param statsReceiver stats
- *
- * @return Finagle HTTP Client
- */
- def buildFinagleHttpClient(
- requestTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- statsReceiver: StatsReceiver,
- ): Http.Client =
- Http.client
- .withStatsReceiver(statsReceiver)
- .withRequestTimeout(requestTimeout)
- .withTransport.connectTimeout(connectTimeout)
- .withSession.acquisitionTimeout(acquisitionTimeout)
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala
deleted file mode 100644
index a2f4a5764..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.twitter.product_mixer.shared_library.http_client
-
-import com.twitter.finagle.Http
-import com.twitter.finagle.Service
-import com.twitter.finagle.client.Transporter
-import com.twitter.finagle.http.ProxyCredentials
-import com.twitter.finagle.http.Request
-import com.twitter.finagle.http.Response
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClient
-import com.twitter.util.Duration
-
-object FinagleHttpClientWithProxyBuilder {
-
- /**
- * Build a Finagle HTTP client with Egress Proxy support using Credentials
- *
- * @param twitterProxyHostPort Twitter egress proxy host port
- * @param remoteProxyHostPort Remote proxy host port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param proxyCredentials Proxy credentials
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP client with Egress Proxy support using Credentials
- */
- def buildFinagleHttpClientWithCredentialProxy(
- twitterProxyHostPort: HttpHostPort,
- remoteProxyHostPort: HttpHostPort,
- requestTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- proxyCredentials: ProxyCredentials,
- statsReceiver: StatsReceiver,
- ): Http.Client = {
- val httpClient = buildFinagleHttpClient(
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- statsReceiver = statsReceiver
- )
-
- httpClient.withTransport
- .httpProxyTo(
- host = remoteProxyHostPort.toString,
- credentials = Transporter.Credentials(proxyCredentials.username, proxyCredentials.password))
- .withTls(remoteProxyHostPort.host)
- }
-
- /**
- * Build a Finagle HTTP client with Egress Proxy support
- *
- * @param twitterProxyHostPort Twitter egress proxy host port
- * @param remoteProxyHostPort Remote proxy host port
- * @param requestTimeout HTTP client request timeout
- * @param connectTimeout HTTP client transport connect timeout
- * @param acquisitionTimeout HTTP client session acquisition timeout
- * @param statsReceiver Stats
- *
- * @return Finagle HTTP client with Egress Proxy support
- */
- def buildFinagleHttpClientWithProxy(
- twitterProxyHostPort: HttpHostPort,
- remoteProxyHostPort: HttpHostPort,
- requestTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- statsReceiver: StatsReceiver,
- ): Http.Client = {
- val httpClient = buildFinagleHttpClient(
- requestTimeout = requestTimeout,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- statsReceiver = statsReceiver
- )
-
- httpClient.withTransport
- .httpProxyTo(remoteProxyHostPort.toString)
- .withTls(remoteProxyHostPort.host)
- }
-
- /**
- * Build a Finagle HTTP service with Egress Proxy support
- *
- * @param finagleHttpClientWithProxy Finagle HTTP client from which to build the service
- * @param twitterProxyHostPort Twitter egress proxy host port
- *
- * @return Finagle HTTP service with Egress Proxy support
- */
- def buildFinagleHttpServiceWithProxy(
- finagleHttpClientWithProxy: Http.Client,
- twitterProxyHostPort: HttpHostPort
- ): Service[Request, Response] = {
- finagleHttpClientWithProxy.newService(twitterProxyHostPort.toString)
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala
deleted file mode 100644
index ceab3d24e..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.twitter.product_mixer.shared_library.http_client
-
-case class HttpHostPort(host: String, port: Int) {
- override val toString: String = s"$host:$port"
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD
deleted file mode 100644
index 3de790d1f..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD
+++ /dev/null
@@ -1,24 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication",
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authorization",
- "finagle/finagle-core/src/main",
- "finagle/finagle-thriftmux/src/main/scala",
- "src/scala/com/twitter/storehaus_internal/manhattan/config",
- "src/thrift/com/twitter/manhattan:v1-scala",
- "storage/clients/manhattan",
- "util/util-core",
- ],
- exports = [
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication",
- "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authorization",
- "finagle/finagle-core/src/main",
- "src/scala/com/twitter/storehaus_internal/manhattan/config",
- "storage/clients/manhattan",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala
deleted file mode 100644
index a9903a4e0..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.twitter.product_mixer.shared_library.manhattan_client
-
-import com.twitter.finagle.mtls.authentication.EmptyServiceIdentifier
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.ssl.OpportunisticTls
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.manhattan.v1.{thriftscala => mh}
-import com.twitter.storage.client.manhattan.kv.Experiments
-import com.twitter.storage.client.manhattan.kv.Experiments.Experiment
-import com.twitter.storage.client.manhattan.kv.Guarantee
-import com.twitter.storage.client.manhattan.kv.ManhattanKVClient
-import com.twitter.storage.client.manhattan.kv.ManhattanKVClientMtlsParams
-import com.twitter.storage.client.manhattan.kv.ManhattanKVEndpoint
-import com.twitter.storage.client.manhattan.kv.ManhattanKVEndpointBuilder
-import com.twitter.storage.client.manhattan.kv.NoMtlsParams
-import com.twitter.storehaus_internal.manhattan.ManhattanCluster
-import com.twitter.util.Duration
-
-object ManhattanClientBuilder {
-
- /**
- * Build a ManhattanKVClient/Endpoint [[ManhattanKVEndpoint]] / [[ManhattanKVClient]]
- *
- * @param cluster Manhattan cluster
- * @param appId Manhattan appid
- * @param numTries Max number of times to try
- * @param maxTimeout Max request timeout
- * @param maxItemsPerRequest Max items per request
- * @param guarantee Consistency guarantee
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param statsReceiver Stats
- * @param experiments MH client experiments to include
- * @return ManhattanKVEndpoint
- */
- def buildManhattanEndpoint(
- cluster: ManhattanCluster,
- appId: String,
- numTries: Int,
- maxTimeout: Duration,
- guarantee: Guarantee,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver,
- maxItemsPerRequest: Int = 100,
- experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer)
- ): ManhattanKVEndpoint = {
- val client = buildManhattanClient(
- cluster,
- appId,
- serviceIdentifier,
- experiments
- )
-
- ManhattanKVEndpointBuilder(client)
- .defaultGuarantee(guarantee)
- .defaultMaxTimeout(maxTimeout)
- .maxRetryCount(numTries)
- .maxItemsPerRequest(maxItemsPerRequest)
- .statsReceiver(statsReceiver)
- .build()
- }
-
- /**
- * Build a ManhattanKVClient
- *
- * @param cluster Manhattan cluster
- * @param appId Manhattan appid
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param experiments MH client experiments to include
- *
- * @return ManhattanKVClient
- */
- def buildManhattanClient(
- cluster: ManhattanCluster,
- appId: String,
- serviceIdentifier: ServiceIdentifier,
- experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer)
- ): ManhattanKVClient = {
- val mtlsParams = serviceIdentifier match {
- case EmptyServiceIdentifier => NoMtlsParams
- case serviceIdentifier =>
- ManhattanKVClientMtlsParams(
- serviceIdentifier = serviceIdentifier,
- opportunisticTls = OpportunisticTls.Required)
- }
-
- val label = s"manhattan/${cluster.prefix}"
-
- new ManhattanKVClient(
- appId = appId,
- dest = cluster.wilyName,
- mtlsParams = mtlsParams,
- label = label,
- experiments = experiments
- )
- }
-
- def buildManhattanV1FinagleClient(
- cluster: ManhattanCluster,
- serviceIdentifier: ServiceIdentifier,
- experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer)
- ): mh.ManhattanCoordinator.MethodPerEndpoint = {
- val mtlsParams = serviceIdentifier match {
- case EmptyServiceIdentifier => NoMtlsParams
- case serviceIdentifier =>
- ManhattanKVClientMtlsParams(
- serviceIdentifier = serviceIdentifier,
- opportunisticTls = OpportunisticTls.Required)
- }
-
- val label = s"manhattan/${cluster.prefix}"
-
- Experiments
- .clientWithExperiments(experiments, mtlsParams)
- .build[mh.ManhattanCoordinator.MethodPerEndpoint](cluster.wilyName, label)
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD
deleted file mode 100644
index dfd7ba2b1..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD
+++ /dev/null
@@ -1,18 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-memcached/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "servo/repo/src/main/scala",
- ],
- exports = [
- "finagle/finagle-memcached/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "servo/repo/src/main/scala",
- ],
-)
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala
deleted file mode 100644
index 62453afbd..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.twitter.product_mixer.shared_library.memcached_client
-
-import com.twitter.finagle.memcached.Client
-import com.twitter.finagle.memcached.protocol.Command
-import com.twitter.finagle.memcached.protocol.Response
-import com.twitter.finagle.mtls.client.MtlsStackClient._
-import com.twitter.finagle.service.RetryExceptionsFilter
-import com.twitter.finagle.service.RetryPolicy
-import com.twitter.finagle.service.TimeoutFilter
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finagle.util.DefaultTimer
-import com.twitter.finagle.GlobalRequestTimeoutException
-import com.twitter.finagle.Memcached
-import com.twitter.finagle.liveness.FailureAccrualFactory
-import com.twitter.finagle.liveness.FailureAccrualPolicy
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.hashing.KeyHasher
-import com.twitter.util.Duration
-
-object MemcachedClientBuilder {
-
- /**
- * Build a Finagle Memcached [[Client]].
- *
- * @param destName Destination as a Wily path e.g. "/s/sample/sample".
- * @param numTries Maximum number of times to try.
- * @param requestTimeout Thrift client timeout per request. The Finagle default
- * is unbounded which is almost never optimal.
- * @param globalTimeout Thrift client total timeout. The Finagle default is
- * unbounded which is almost never optimal.
- * @param connectTimeout Thrift client transport connect timeout. The Finagle
- * default of one second is reasonable but we lower this
- * to match acquisitionTimeout for consistency.
- * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle
- * default is unbounded which is almost never optimal.
- * @param serviceIdentifier Service ID used to S2S Auth.
- * @param statsReceiver Stats.
- * @param failureAccrualPolicy Policy to determine when to mark a cache server as dead.
- * Memcached client will use default failure accrual policy
- * if it is not set.
- * @param keyHasher Hash algorithm that hashes a key into a 32-bit or 64-bit
- * number. Memcached client will use default hash algorithm
- * if it is not set.
- *
- * @see [[https://confluence.twitter.biz/display/CACHE/Finagle-memcached+User+Guide user guide]]
- * @return Finagle Memcached [[Client]]
- */
- def buildMemcachedClient(
- destName: String,
- numTries: Int,
- requestTimeout: Duration,
- globalTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver,
- failureAccrualPolicy: Option[FailureAccrualPolicy] = None,
- keyHasher: Option[KeyHasher] = None
- ): Client = {
- buildRawMemcachedClient(
- numTries,
- requestTimeout,
- globalTimeout,
- connectTimeout,
- acquisitionTimeout,
- serviceIdentifier,
- statsReceiver,
- failureAccrualPolicy,
- keyHasher
- ).newRichClient(destName)
- }
-
- def buildRawMemcachedClient(
- numTries: Int,
- requestTimeout: Duration,
- globalTimeout: Duration,
- connectTimeout: Duration,
- acquisitionTimeout: Duration,
- serviceIdentifier: ServiceIdentifier,
- statsReceiver: StatsReceiver,
- failureAccrualPolicy: Option[FailureAccrualPolicy] = None,
- keyHasher: Option[KeyHasher] = None
- ): Memcached.Client = {
- val globalTimeoutFilter = new TimeoutFilter[Command, Response](
- timeout = globalTimeout,
- exception = new GlobalRequestTimeoutException(globalTimeout),
- timer = DefaultTimer)
- val retryFilter = new RetryExceptionsFilter[Command, Response](
- RetryPolicy.tries(numTries),
- DefaultTimer,
- statsReceiver)
-
- val client = Memcached.client.withTransport
- .connectTimeout(connectTimeout)
- .withMutualTls(serviceIdentifier)
- .withSession
- .acquisitionTimeout(acquisitionTimeout)
- .withRequestTimeout(requestTimeout)
- .withStatsReceiver(statsReceiver)
- .filtered(globalTimeoutFilter.andThen(retryFilter))
-
- (keyHasher, failureAccrualPolicy) match {
- case (Some(hasher), Some(policy)) =>
- client
- .withKeyHasher(hasher)
- .configured(FailureAccrualFactory.Param(() => policy))
- case (Some(hasher), None) =>
- client
- .withKeyHasher(hasher)
- case (None, Some(policy)) =>
- client
- .configured(FailureAccrualFactory.Param(() => policy))
- case _ =>
- client
- }
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD
deleted file mode 100644
index 325ddbae3..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- platform = "java8",
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "servo/util",
- "stitch/stitch-core",
- "util/util-core:util-core-util",
- "util/util-stats",
- ],
- exports = [
- "servo/util",
- "stitch/stitch-core",
- "util/util-core:util-core-util",
- "util/util-stats",
- ],
-)
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala
deleted file mode 100644
index df9e8389d..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala
+++ /dev/null
@@ -1,203 +0,0 @@
-package com.twitter.product_mixer.shared_library.observer
-
-import com.twitter.finagle.stats.Counter
-import com.twitter.finagle.stats.RollupStatsReceiver
-import com.twitter.finagle.stats.Stat
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.servo.util.CancelledExceptionExtractor
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import com.twitter.util.Duration
-import com.twitter.util.Future
-import com.twitter.util.Throwables
-import com.twitter.util.Try
-
-/**
- * Helper functions to observe requests, success, failures, cancellations, exceptions, and latency.
- * Supports native functions and asynchronous operations.
- */
-object Observer {
- val Requests = "requests"
- val Success = "success"
- val Failures = "failures"
- val Cancelled = "cancelled"
- val Latency = "latency_ms"
-
- /**
- * Helper function to observe a stitch
- *
- * @see [[StitchObserver]]
- */
- def stitch[T](statsReceiver: StatsReceiver, scopes: String*): StitchObserver[T] =
- new StitchObserver[T](statsReceiver, scopes)
-
- /**
- * Helper function to observe an arrow
- *
- * @see [[ArrowObserver]]
- */
- def arrow[In, Out](statsReceiver: StatsReceiver, scopes: String*): ArrowObserver[In, Out] =
- new ArrowObserver[In, Out](statsReceiver, scopes)
-
- /**
- * Helper function to observe a future
- *
- * @see [[FutureObserver]]
- */
- def future[T](statsReceiver: StatsReceiver, scopes: String*): FutureObserver[T] =
- new FutureObserver[T](statsReceiver, scopes)
-
- /**
- * Helper function to observe a function
- *
- * @see [[FunctionObserver]]
- */
- def function[T](statsReceiver: StatsReceiver, scopes: String*): FunctionObserver[T] =
- new FunctionObserver[T](statsReceiver, scopes)
-
- /**
- * [[StitchObserver]] can record latency stats, success counters, and
- * detailed failure stats for the results of a Stitch computation.
- */
- class StitchObserver[T](
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[T] {
-
- /**
- * Record stats for the provided Stitch.
- * The result of the computation is passed through.
- *
- * @note the provided Stitch must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(stitch: => Stitch[T]): Stitch[T] =
- Stitch.time(stitch).map(observe.tupled).lowerFromTry
- }
-
- /**
- * [[ArrowObserver]] can record the latency stats, success counters, and
- * detailed failure stats for the result of an Arrow computation.
- * The result of the computation is passed through.
- */
- class ArrowObserver[In, Out](
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[Out] {
-
- /**
- * Returns a new Arrow that records stats when it's run.
- * The result of the Arrow is passed through.
- *
- * @note the provided Arrow must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(arrow: Arrow[In, Out]): Arrow[In, Out] =
- Arrow.time(arrow).map(observe.tupled).lowerFromTry
- }
-
- /**
- * [[FutureObserver]] can record latency stats, success counters, and
- * detailed failure stats for the results of a Future computation.
- */
- class FutureObserver[T](
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[T] {
-
- /**
- * Record stats for the provided Future.
- * The result of the computation is passed through.
- *
- * @note the provided Future must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(future: => Future[T]): Future[T] =
- Stat
- .timeFuture(latencyStat)(future)
- .onSuccess(observeSuccess)
- .onFailure(observeFailure)
- }
-
- /**
- * [[FunctionObserver]] can record latency stats, success counters, and
- * detailed failure stats for the results of a computation computation.
- */
- class FunctionObserver[T](
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[T] {
-
- /**
- * Record stats for the provided computation.
- * The result of the computation is passed through.
- *
- * @note the provided computation must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(f: => T): T = {
- Try(Stat.time(latencyStat)(f))
- .onSuccess(observeSuccess)
- .onFailure(observeFailure)
- .apply()
- }
- }
-
- /** [[Observer]] provides methods for recording latency, success, and failure stats */
- trait Observer[T] {
- protected val statsReceiver: StatsReceiver
-
- /** Scopes that prefix all stats */
- protected val scopes: Seq[String]
-
- private val rollupStatsReceiver = new RollupStatsReceiver(statsReceiver.scope(scopes: _*))
- private val requestsCounter: Counter = statsReceiver.counter(scopes :+ Requests: _*)
- private val successCounter: Counter = statsReceiver.counter(scopes :+ Success: _*)
-
- // create the stats so their metrics paths are always present but
- // defer to the [[RollupStatsReceiver]] to increment these stats
- rollupStatsReceiver.counter(Failures)
- rollupStatsReceiver.counter(Cancelled)
-
- /** Serialize a throwable and it's causes into a seq of Strings for scoping metrics */
- protected def serializeThrowable(throwable: Throwable): Seq[String] =
- Throwables.mkString(throwable)
-
- /** Used to record latency in milliseconds */
- protected val latencyStat: Stat = statsReceiver.stat(scopes :+ Latency: _*)
-
- /** Records the latency from a [[Duration]] */
- protected val observeLatency: Duration => Unit = { latency =>
- latencyStat.add(latency.inMilliseconds)
- }
-
- /** Records successes */
- protected val observeSuccess: T => Unit = { _ =>
- requestsCounter.incr()
- successCounter.incr()
- }
-
- /** Records failures and failure details */
- protected val observeFailure: Throwable => Unit = {
- case CancelledExceptionExtractor(throwable) =>
- requestsCounter.incr()
- rollupStatsReceiver.counter(Cancelled +: serializeThrowable(throwable): _*).incr()
- case throwable =>
- requestsCounter.incr()
- rollupStatsReceiver.counter(Failures +: serializeThrowable(throwable): _*).incr()
- }
-
- /** Records the latency, successes, and failures */
- protected val observe: (Try[T], Duration) => Try[T] =
- (response: Try[T], runDuration: Duration) => {
- observeLatency(runDuration)
- response
- .onSuccess(observeSuccess)
- .onFailure(observeFailure)
- }
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala
deleted file mode 100644
index e77676509..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala
+++ /dev/null
@@ -1,281 +0,0 @@
-package com.twitter.product_mixer.shared_library.observer
-
-import com.twitter.finagle.stats.Counter
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.shared_library.observer.Observer.ArrowObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.FunctionObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.Observer
-import com.twitter.product_mixer.shared_library.observer.Observer.StitchObserver
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import com.twitter.util.Future
-import com.twitter.util.Try
-
-/**
- * Helper functions to observe requests, successes, failures, cancellations, exceptions, latency,
- * and result counts. Supports native functions and asynchronous operations.
- */
-object ResultsObserver {
- val Total = "total"
- val Found = "found"
- val NotFound = "not_found"
-
- /**
- * Helper function to observe a stitch and result counts
- *
- * @see [[StitchResultsObserver]]
- */
- def stitchResults[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): StitchResultsObserver[T] = {
- new StitchResultsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a stitch and traversable (e.g. Seq, Set) result counts
- *
- * @see [[StitchResultsObserver]]
- */
- def stitchResults[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): StitchResultsObserver[T] = {
- new StitchResultsObserver[T](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and result counts
- *
- * @see [[ArrowResultsObserver]]
- */
- def arrowResults[In, Out](
- size: Out => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): ArrowResultsObserver[In, Out] = {
- new ArrowResultsObserver[In, Out](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts
- *
- * @see [[ArrowResultsObserver]]
- */
- def arrowResults[In, Out <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): ArrowResultsObserver[In, Out] = {
- new ArrowResultsObserver[In, Out](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and result counts
- *
- * @see [[TransformingArrowResultsObserver]]
- */
- def transformingArrowResults[In, Out, Transformed](
- transformer: Out => Try[Transformed],
- size: Transformed => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): TransformingArrowResultsObserver[In, Out, Transformed] = {
- new TransformingArrowResultsObserver[In, Out, Transformed](
- transformer,
- size,
- statsReceiver,
- scopes)
- }
-
- /**
- * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts
- *
- * @see [[TransformingArrowResultsObserver]]
- */
- def transformingArrowResults[In, Out, Transformed <: TraversableOnce[_]](
- transformer: Out => Try[Transformed],
- statsReceiver: StatsReceiver,
- scopes: String*
- ): TransformingArrowResultsObserver[In, Out, Transformed] = {
- new TransformingArrowResultsObserver[In, Out, Transformed](
- transformer,
- _.size,
- statsReceiver,
- scopes)
- }
-
- /**
- * Helper function to observe a future and result counts
- *
- * @see [[FutureResultsObserver]]
- */
- def futureResults[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FutureResultsObserver[T] = {
- new FutureResultsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a future and traversable (e.g. Seq, Set) result counts
- *
- * @see [[FutureResultsObserver]]
- */
- def futureResults[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FutureResultsObserver[T] = {
- new FutureResultsObserver[T](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a function and result counts
- *
- * @see [[FunctionResultsObserver]]
- */
- def functionResults[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FunctionResultsObserver[T] = {
- new FunctionResultsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a function and traversable (e.g. Seq, Set) result counts
- *
- * @see [[FunctionResultsObserver]]
- */
- def functionResults[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FunctionResultsObserver[T] = {
- new FunctionResultsObserver[T](_.size, statsReceiver, scopes)
- }
-
- /** [[StitchObserver]] that also records result size */
- class StitchResultsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends StitchObserver[T](statsReceiver, scopes)
- with ResultsObserver[T] {
-
- override def apply(stitch: => Stitch[T]): Stitch[T] =
- super
- .apply(stitch)
- .onSuccess(observeResults)
- }
-
- /** [[ArrowObserver]] that also records result size */
- class ArrowResultsObserver[In, Out](
- override val size: Out => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends ArrowObserver[In, Out](statsReceiver, scopes)
- with ResultsObserver[Out] {
-
- override def apply(arrow: Arrow[In, Out]): Arrow[In, Out] =
- super
- .apply(arrow)
- .onSuccess(observeResults)
- }
-
- /**
- * [[TransformingArrowResultsObserver]] functions like an [[ArrowObserver]] except
- * that it transforms the result using [[transformer]] before recording stats.
- *
- * The original non-transformed result is then returned.
- */
- class TransformingArrowResultsObserver[In, Out, Transformed](
- val transformer: Out => Try[Transformed],
- override val size: Transformed => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[Transformed]
- with ResultsObserver[Transformed] {
-
- /**
- * Returns a new Arrow that records stats on the result after applying [[transformer]] when it's run.
- * The original, non-transformed, result of the Arrow is passed through.
- *
- * @note the provided Arrow must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = {
- Arrow
- .time(arrow)
- .map {
- case (response, stitchRunDuration) =>
- observe(response.flatMap(transformer), stitchRunDuration)
- .onSuccess(observeResults)
- response
- }.lowerFromTry
- }
- }
-
- /** [[FutureObserver]] that also records result size */
- class FutureResultsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends FutureObserver[T](statsReceiver, scopes)
- with ResultsObserver[T] {
-
- override def apply(future: => Future[T]): Future[T] =
- super
- .apply(future)
- .onSuccess(observeResults)
- }
-
- /** [[FunctionObserver]] that also records result size */
- class FunctionResultsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends FunctionObserver[T](statsReceiver, scopes)
- with ResultsObserver[T] {
-
- override def apply(f: => T): T = observeResults(super.apply(f))
- }
-
- /** [[ResultsObserver]] provides methods for recording stats for the result size */
- trait ResultsObserver[T] {
- protected val statsReceiver: StatsReceiver
-
- /** Scopes that prefix all stats */
- protected val scopes: Seq[String]
-
- protected val totalCounter: Counter = statsReceiver.counter(scopes :+ Total: _*)
- protected val foundCounter: Counter = statsReceiver.counter(scopes :+ Found: _*)
- protected val notFoundCounter: Counter = statsReceiver.counter(scopes :+ NotFound: _*)
-
- /** given a [[T]] returns it's size. */
- protected val size: T => Int
-
- /** Records the size of the `results` using [[size]] and return the original value. */
- protected def observeResults(results: T): T = {
- val resultsSize = size(results)
- observeResultsWithSize(results, resultsSize)
- }
-
- /**
- * Records the `resultsSize` and returns the `results`
- *
- * This is useful if the size is already available and is expensive to calculate.
- */
- protected def observeResultsWithSize(results: T, resultsSize: Int): T = {
- if (resultsSize > 0) {
- totalCounter.incr(resultsSize)
- foundCounter.incr()
- } else {
- notFoundCounter.incr()
- }
- results
- }
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala
deleted file mode 100644
index a637e23d8..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala
+++ /dev/null
@@ -1,243 +0,0 @@
-package com.twitter.product_mixer.shared_library.observer
-
-import com.twitter.finagle.stats.Stat
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.product_mixer.shared_library.observer.Observer.ArrowObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.FunctionObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver
-import com.twitter.product_mixer.shared_library.observer.Observer.Observer
-import com.twitter.product_mixer.shared_library.observer.Observer.StitchObserver
-import com.twitter.product_mixer.shared_library.observer.ResultsObserver.ResultsObserver
-import com.twitter.stitch.Arrow
-import com.twitter.stitch.Stitch
-import com.twitter.util.Future
-import com.twitter.util.Try
-
-/**
- * Helper functions to observe requests, successes, failures, cancellations, exceptions, latency,
- * and result counts and time-series stats. Supports native functions and asynchronous operations.
- *
- * Note that since time-series stats are expensive to compute (relative to counters), prefer
- * [[ResultsObserver]] unless a time-series stat is needed.
- */
-object ResultsStatsObserver {
- val Size = "size"
-
- /**
- * Helper function to observe a stitch and result counts and time-series stats
- */
- def stitchResultsStats[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): StitchResultsStatsObserver[T] = {
- new StitchResultsStatsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a stitch and traversable (e.g. Seq, Set) result counts and
- * time-series stats
- */
- def stitchResultsStats[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): StitchResultsStatsObserver[T] = {
- new StitchResultsStatsObserver[T](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and result counts and time-series stats
- */
- def arrowResultsStats[T, U](
- size: U => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): ArrowResultsStatsObserver[T, U] = {
- new ArrowResultsStatsObserver[T, U](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts and
- * * time-series stats
- */
- def arrowResultsStats[T, U <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): ArrowResultsStatsObserver[T, U] = {
- new ArrowResultsStatsObserver[T, U](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe an arrow and result counts
- *
- * @see [[TransformingArrowResultsStatsObserver]]
- */
- def transformingArrowResultsStats[In, Out, Transformed](
- transformer: Out => Try[Transformed],
- size: Transformed => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): TransformingArrowResultsStatsObserver[In, Out, Transformed] = {
- new TransformingArrowResultsStatsObserver[In, Out, Transformed](
- transformer,
- size,
- statsReceiver,
- scopes)
- }
-
- /**
- * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts
- *
- * @see [[TransformingArrowResultsStatsObserver]]
- */
- def transformingArrowResultsStats[In, Out, Transformed <: TraversableOnce[_]](
- transformer: Out => Try[Transformed],
- statsReceiver: StatsReceiver,
- scopes: String*
- ): TransformingArrowResultsStatsObserver[In, Out, Transformed] = {
- new TransformingArrowResultsStatsObserver[In, Out, Transformed](
- transformer,
- _.size,
- statsReceiver,
- scopes)
- }
-
- /**
- * Helper function to observe a future and result counts and time-series stats
- */
- def futureResultsStats[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FutureResultsStatsObserver[T] = {
- new FutureResultsStatsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function to observe a future and traversable (e.g. Seq, Set) result counts and
- * time-series stats
- */
- def futureResultsStats[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FutureResultsStatsObserver[T] = {
- new FutureResultsStatsObserver[T](_.size, statsReceiver, scopes)
- }
-
- /**
- * Helper function observe a function and result counts and time-series stats
- */
- def functionResultsStats[T](
- size: T => Int,
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FunctionResultsStatsObserver[T] = {
- new FunctionResultsStatsObserver[T](size, statsReceiver, scopes)
- }
-
- /**
- * Helper function observe a function and traversable (e.g. Seq, Set) result counts and
- * time-series stats
- */
- def functionResultsStats[T <: TraversableOnce[_]](
- statsReceiver: StatsReceiver,
- scopes: String*
- ): FunctionResultsStatsObserver[T] = {
- new FunctionResultsStatsObserver[T](_.size, statsReceiver, scopes)
- }
-
- class StitchResultsStatsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends StitchObserver[T](statsReceiver, scopes)
- with ResultsStatsObserver[T] {
-
- override def apply(stitch: => Stitch[T]): Stitch[T] =
- super
- .apply(stitch)
- .onSuccess(observeResults)
- }
-
- class ArrowResultsStatsObserver[T, U](
- override val size: U => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends ArrowObserver[T, U](statsReceiver, scopes)
- with ResultsStatsObserver[U] {
-
- override def apply(arrow: Arrow[T, U]): Arrow[T, U] =
- super
- .apply(arrow)
- .onSuccess(observeResults)
- }
-
- /**
- * [[TransformingArrowResultsStatsObserver]] functions like an [[ArrowObserver]] except
- * that it transforms the result using [[transformer]] before recording stats.
- *
- * The original non-transformed result is then returned.
- */
- class TransformingArrowResultsStatsObserver[In, Out, Transformed](
- val transformer: Out => Try[Transformed],
- override val size: Transformed => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends Observer[Transformed]
- with ResultsStatsObserver[Transformed] {
-
- /**
- * Returns a new Arrow that records stats on the result after applying [[transformer]] when it's run.
- * The original, non-transformed, result of the Arrow is passed through.
- *
- * @note the provided Arrow must contain the parts that need to be timed.
- * Using this on just the result of the computation the latency stat
- * will be incorrect.
- */
- def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = {
- Arrow
- .time(arrow)
- .map {
- case (response, stitchRunDuration) =>
- observe(response.flatMap(transformer), stitchRunDuration)
- .onSuccess(observeResults)
- response
- }.lowerFromTry
- }
- }
-
- class FutureResultsStatsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends FutureObserver[T](statsReceiver, scopes)
- with ResultsStatsObserver[T] {
-
- override def apply(future: => Future[T]): Future[T] =
- super
- .apply(future)
- .onSuccess(observeResults)
- }
-
- class FunctionResultsStatsObserver[T](
- override val size: T => Int,
- override val statsReceiver: StatsReceiver,
- override val scopes: Seq[String])
- extends FunctionObserver[T](statsReceiver, scopes)
- with ResultsStatsObserver[T] {
-
- override def apply(f: => T): T = {
- observeResults(super.apply(f))
- }
- }
-
- trait ResultsStatsObserver[T] extends ResultsObserver[T] {
- private val sizeStat: Stat = statsReceiver.stat(scopes :+ Size: _*)
-
- protected override def observeResults(results: T): T = {
- val resultsSize = size(results)
- sizeStat.add(resultsSize)
- observeResultsWithSize(results, resultsSize)
- }
- }
-}
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD
deleted file mode 100644
index 8569f2d61..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD
+++ /dev/null
@@ -1,20 +0,0 @@
-scala_library(
- sources = ["*.scala"],
- compiler_option_sets = ["fatal_warnings"],
- strict_deps = True,
- tags = ["bazel-compatible"],
- dependencies = [
- "finagle/finagle-core/src/main",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "util/util-core",
- ],
- exports = [
- "finagle/finagle-core/src/main",
- "finagle/finagle-thriftmux/src/main/scala",
- "finatra-internal/mtls-http/src/main/scala",
- "finatra-internal/mtls-thriftmux/src/main/scala",
- "util/util-core",
- ],
-)
diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala
deleted file mode 100644
index b8c25b5a1..000000000
--- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala
+++ /dev/null
@@ -1,198 +0,0 @@
-package com.twitter.product_mixer.shared_library.thrift_client
-
-import com.twitter.conversions.DurationOps._
-import com.twitter.finagle.ThriftMux
-import com.twitter.finagle.mtls.authentication.ServiceIdentifier
-import com.twitter.finagle.mtls.client.MtlsStackClient._
-import com.twitter.finagle.stats.StatsReceiver
-import com.twitter.finagle.thrift.ClientId
-import com.twitter.finagle.thrift.service.Filterable
-import com.twitter.finagle.thrift.service.MethodPerEndpointBuilder
-import com.twitter.finagle.thrift.service.ServicePerEndpointBuilder
-import com.twitter.finagle.thriftmux.MethodBuilder
-import com.twitter.util.Duration
-import org.apache.thrift.protocol.TProtocolFactory
-
-sealed trait Idempotency
-case object NonIdempotent extends Idempotency
-case class Idempotent(maxExtraLoadPercent: Double) extends Idempotency
-
-object FinagleThriftClientBuilder {
-
- /**
- * Library to build a Finagle Thrift method per endpoint client is a less error-prone way when
- * compared to the builders in Finagle. This is achieved by requiring values for fields that should
- * always be set in practice. For example, request timeouts in Finagle are unbounded when not
- * explicitly set, and this method requires that timeout durations are passed into the method and
- * set on the Finagle builder.
- *
- * Usage of
- * [[com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule]] is almost always preferred,
- * and the Product Mixer component library [[com.twitter.product_mixer.component_library.module]]
- * package contains numerous examples. However, if multiple versions of a client are needed e.g.
- * for different timeout settings, this method is useful to easily provide multiple variants.
- *
- * @example
- * {{{
- * final val SampleServiceClientName = "SampleServiceClient"
- * @Provides
- * @Singleton
- * @Named(SampleServiceClientName)
- * def provideSampleServiceClient(
- * serviceIdentifier: ServiceIdentifier,
- * clientId: ClientId,
- * statsReceiver: StatsReceiver,
- * ): SampleService.MethodPerEndpoint =
- * buildFinagleMethodPerEndpoint[SampleService.ServicePerEndpoint, SampleService.MethodPerEndpoint](
- * serviceIdentifier = serviceIdentifier,
- * clientId = clientId,
- * dest = "/s/sample/sample",
- * label = "sample",
- * statsReceiver = statsReceiver,
- * idempotency = Idempotent(5.percent),
- * timeoutPerRequest = 200.milliseconds,
- * timeoutTotal = 400.milliseconds
- * )
- * }}}
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param clientId Client ID
- * @param dest Destination as a Wily path e.g. "/s/sample/sample"
- * @param label Label of the client
- * @param statsReceiver Stats
- * @param idempotency Idempotency semantics of the client
- * @param timeoutPerRequest Thrift client timeout per request. The Finagle default is
- * unbounded which is almost never optimal.
- * @param timeoutTotal Thrift client total timeout. The Finagle default is
- * unbounded which is almost never optimal.
- * If the client is set as idempotent, which adds a
- * [[com.twitter.finagle.client.BackupRequestFilter]],
- * be sure to leave enough room for the backup request. A
- * reasonable (albeit usually too large) starting point is to
- * make the total timeout 2x relative to the per request timeout.
- * If the client is set as non-idempotent, the total timeout and
- * the per request timeout should be the same, as there will be
- * no backup requests.
- * @param connectTimeout Thrift client transport connect timeout. The Finagle default
- * of one second is reasonable but we lower this to match
- * acquisitionTimeout for consistency.
- * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle default
- * is unbounded which is almost never optimal.
- * @param protocolFactoryOverride Override the default protocol factory
- * e.g. [[org.apache.thrift.protocol.TCompactProtocol.Factory]]
- * @param servicePerEndpointBuilder implicit service per endpoint builder
- * @param methodPerEndpointBuilder implicit method per endpoint builder
- *
- * @see [[https://twitter.github.io/finagle/guide/MethodBuilder.html user guide]]
- * @see [[https://twitter.github.io/finagle/guide/MethodBuilder.html#idempotency user guide]]
- * @return method per endpoint Finagle Thrift Client
- */
- def buildFinagleMethodPerEndpoint[
- ServicePerEndpoint <: Filterable[ServicePerEndpoint],
- MethodPerEndpoint
- ](
- serviceIdentifier: ServiceIdentifier,
- clientId: ClientId,
- dest: String,
- label: String,
- statsReceiver: StatsReceiver,
- idempotency: Idempotency,
- timeoutPerRequest: Duration,
- timeoutTotal: Duration,
- connectTimeout: Duration = 500.milliseconds,
- acquisitionTimeout: Duration = 500.milliseconds,
- protocolFactoryOverride: Option[TProtocolFactory] = None,
- )(
- implicit servicePerEndpointBuilder: ServicePerEndpointBuilder[ServicePerEndpoint],
- methodPerEndpointBuilder: MethodPerEndpointBuilder[ServicePerEndpoint, MethodPerEndpoint]
- ): MethodPerEndpoint = {
- val service: ServicePerEndpoint = buildFinagleServicePerEndpoint(
- serviceIdentifier = serviceIdentifier,
- clientId = clientId,
- dest = dest,
- label = label,
- statsReceiver = statsReceiver,
- idempotency = idempotency,
- timeoutPerRequest = timeoutPerRequest,
- timeoutTotal = timeoutTotal,
- connectTimeout = connectTimeout,
- acquisitionTimeout = acquisitionTimeout,
- protocolFactoryOverride = protocolFactoryOverride
- )
-
- ThriftMux.Client.methodPerEndpoint(service)
- }
-
- /**
- * Build a Finagle Thrift service per endpoint client.
- *
- * @note [[buildFinagleMethodPerEndpoint]] should be preferred over the service per endpoint variant
- *
- * @param serviceIdentifier Service ID used to S2S Auth
- * @param clientId Client ID
- * @param dest Destination as a Wily path e.g. "/s/sample/sample"
- * @param label Label of the client
- * @param statsReceiver Stats
- * @param idempotency Idempotency semantics of the client
- * @param timeoutPerRequest Thrift client timeout per request. The Finagle default is
- * unbounded which is almost never optimal.
- * @param timeoutTotal Thrift client total timeout. The Finagle default is
- * unbounded which is almost never optimal.
- * If the client is set as idempotent, which adds a
- * [[com.twitter.finagle.client.BackupRequestFilter]],
- * be sure to leave enough room for the backup request. A
- * reasonable (albeit usually too large) starting point is to
- * make the total timeout 2x relative to the per request timeout.
- * If the client is set as non-idempotent, the total timeout and
- * the per request timeout should be the same, as there will be
- * no backup requests.
- * @param connectTimeout Thrift client transport connect timeout. The Finagle default
- * of one second is reasonable but we lower this to match
- * acquisitionTimeout for consistency.
- * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle default
- * is unbounded which is almost never optimal.
- * @param protocolFactoryOverride Override the default protocol factory
- * e.g. [[org.apache.thrift.protocol.TCompactProtocol.Factory]]
- *
- * @return service per endpoint Finagle Thrift Client
- */
- def buildFinagleServicePerEndpoint[ServicePerEndpoint <: Filterable[ServicePerEndpoint]](
- serviceIdentifier: ServiceIdentifier,
- clientId: ClientId,
- dest: String,
- label: String,
- statsReceiver: StatsReceiver,
- idempotency: Idempotency,
- timeoutPerRequest: Duration,
- timeoutTotal: Duration,
- connectTimeout: Duration = 500.milliseconds,
- acquisitionTimeout: Duration = 500.milliseconds,
- protocolFactoryOverride: Option[TProtocolFactory] = None,
- )(
- implicit servicePerEndpointBuilder: ServicePerEndpointBuilder[ServicePerEndpoint]
- ): ServicePerEndpoint = {
- val thriftMux: ThriftMux.Client = ThriftMux.client
- .withMutualTls(serviceIdentifier)
- .withClientId(clientId)
- .withLabel(label)
- .withStatsReceiver(statsReceiver)
- .withTransport.connectTimeout(connectTimeout)
- .withSession.acquisitionTimeout(acquisitionTimeout)
-
- val protocolThriftMux: ThriftMux.Client = protocolFactoryOverride
- .map { protocolFactory =>
- thriftMux.withProtocolFactory(protocolFactory)
- }.getOrElse(thriftMux)
-
- val methodBuilder: MethodBuilder = protocolThriftMux
- .methodBuilder(dest)
- .withTimeoutPerRequest(timeoutPerRequest)
- .withTimeoutTotal(timeoutTotal)
-
- val idempotencyMethodBuilder: MethodBuilder = idempotency match {
- case NonIdempotent => methodBuilder.nonIdempotent
- case Idempotent(maxExtraLoad) => methodBuilder.idempotent(maxExtraLoad = maxExtraLoad)
- }
-
- idempotencyMethodBuilder.servicePerEndpoint[ServicePerEndpoint]
- }
-}