mirror of
https://github.com/twitter/the-algorithm.git
synced 2024-06-01 08:48:46 +02:00
143 lines
6.8 KiB
Scala
143 lines
6.8 KiB
Scala
package com.twitter.home_mixer.product.for_you
|
|
|
|
import com.twitter.conversions.DurationOps._
|
|
import com.twitter.home_mixer.marshaller.timelines.ChronologicalCursorUnmarshaller
|
|
import com.twitter.home_mixer.model.request.ForYouProduct
|
|
import com.twitter.home_mixer.model.request.ForYouProductContext
|
|
import com.twitter.home_mixer.model.request.HomeMixerRequest
|
|
import com.twitter.home_mixer.product.for_you.model.ForYouQuery
|
|
import com.twitter.home_mixer.product.for_you.param.ForYouParam.EnablePushToHomeMixerPipelineParam
|
|
import com.twitter.home_mixer.product.for_you.param.ForYouParam.EnableScoredTweetsMixerPipelineParam
|
|
import com.twitter.home_mixer.product.for_you.param.ForYouParam.ServerMaxResultsParam
|
|
import com.twitter.home_mixer.product.for_you.param.ForYouParamConfig
|
|
import com.twitter.home_mixer.service.HomeMixerAccessPolicy.DefaultHomeMixerAccessPolicy
|
|
import com.twitter.home_mixer.service.HomeMixerAlertConfig.DefaultNotificationGroup
|
|
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.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.common.alert.EmptyResponseRateAlert
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.LatencyAlert
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.P99
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.SuccessRateAlert
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.ThroughputAlert
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfAbove
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfBelow
|
|
import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfLatencyAbove
|
|
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.marshalling.request.Product
|
|
import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor
|
|
import com.twitter.product_mixer.core.pipeline.PipelineConfig
|
|
import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest
|
|
import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure
|
|
import com.twitter.product_mixer.core.pipeline.product.ProductPipelineConfig
|
|
import com.twitter.product_mixer.core.product.ProductParamConfig
|
|
import com.twitter.product_mixer.core.util.SortIndexBuilder
|
|
import com.twitter.timelines.configapi.Params
|
|
import com.twitter.timelines.render.{thriftscala => urt}
|
|
import com.twitter.timelines.util.RequestCursorSerializer
|
|
import com.twitter.util.Time
|
|
import com.twitter.util.Try
|
|
import javax.inject.Inject
|
|
import javax.inject.Singleton
|
|
|
|
@Singleton
|
|
class ForYouProductPipelineConfig @Inject() (
|
|
forYouTimelineScorerMixerPipelineConfig: ForYouTimelineScorerMixerPipelineConfig,
|
|
forYouScoredTweetsMixerPipelineConfig: ForYouScoredTweetsMixerPipelineConfig,
|
|
forYouPushToHomeMixerPipelineConfig: ForYouPushToHomeMixerPipelineConfig,
|
|
forYouParamConfig: ForYouParamConfig)
|
|
extends ProductPipelineConfig[HomeMixerRequest, ForYouQuery, urt.TimelineResponse] {
|
|
|
|
override val identifier: ProductPipelineIdentifier = ProductPipelineIdentifier("ForYou")
|
|
|
|
override val product: Product = ForYouProduct
|
|
|
|
override val paramConfig: ProductParamConfig = forYouParamConfig
|
|
|
|
override def pipelineQueryTransformer(
|
|
request: HomeMixerRequest,
|
|
params: Params
|
|
): ForYouQuery = {
|
|
val context = request.productContext match {
|
|
case Some(context: ForYouProductContext) => context
|
|
case _ => throw PipelineFailure(BadRequest, "ForYouProductContext not found")
|
|
}
|
|
|
|
val debugOptions = request.debugParams.flatMap(_.debugOptions)
|
|
|
|
/**
|
|
* Unlike other clients, newly created tweets on Android have the sort index set to the current
|
|
* time instead of the top sort index + 1, so these tweets get stuck at the top of the timeline
|
|
* if subsequent timeline responses use the sort index from the previous response instead of
|
|
* the current time.
|
|
*/
|
|
val pipelineCursor = request.serializedRequestCursor.flatMap { cursor =>
|
|
Try(UrtCursorSerializer.deserializeOrderedCursor(cursor))
|
|
.getOrElse(ChronologicalCursorUnmarshaller(RequestCursorSerializer.deserialize(cursor)))
|
|
.map {
|
|
case topCursor @ UrtOrderedCursor(_, _, Some(TopCursor), _) =>
|
|
val queryTime = debugOptions.flatMap(_.requestTimeOverride).getOrElse(Time.now)
|
|
topCursor.copy(initialSortIndex = SortIndexBuilder.timeToId(queryTime))
|
|
case cursor => cursor
|
|
}
|
|
}
|
|
|
|
ForYouQuery(
|
|
params = params,
|
|
clientContext = request.clientContext,
|
|
features = None,
|
|
pipelineCursor = pipelineCursor,
|
|
requestedMaxResults = Some(params(ServerMaxResultsParam)),
|
|
debugOptions = debugOptions,
|
|
deviceContext = context.deviceContext,
|
|
seenTweetIds = context.seenTweetIds,
|
|
dspClientContext = context.dspClientContext,
|
|
pushToHomeTweetId = context.pushToHomeTweetId
|
|
)
|
|
}
|
|
|
|
override val pipelines: Seq[PipelineConfig] = Seq(
|
|
forYouTimelineScorerMixerPipelineConfig,
|
|
forYouScoredTweetsMixerPipelineConfig,
|
|
forYouPushToHomeMixerPipelineConfig
|
|
)
|
|
|
|
override def pipelineSelector(
|
|
query: ForYouQuery
|
|
): ComponentIdentifier = {
|
|
if (query.pushToHomeTweetId.isDefined && query.params(EnablePushToHomeMixerPipelineParam))
|
|
forYouPushToHomeMixerPipelineConfig.identifier
|
|
else if (query.params(EnableScoredTweetsMixerPipelineParam))
|
|
forYouScoredTweetsMixerPipelineConfig.identifier
|
|
else forYouTimelineScorerMixerPipelineConfig.identifier
|
|
}
|
|
|
|
override val alerts: Seq[Alert] = Seq(
|
|
SuccessRateAlert(
|
|
notificationGroup = DefaultNotificationGroup,
|
|
warnPredicate = TriggerIfBelow(99.9, 20, 30),
|
|
criticalPredicate = TriggerIfBelow(99.9, 30, 30),
|
|
),
|
|
LatencyAlert(
|
|
notificationGroup = DefaultNotificationGroup,
|
|
percentile = P99,
|
|
warnPredicate = TriggerIfLatencyAbove(2300.millis, 15, 30),
|
|
criticalPredicate = TriggerIfLatencyAbove(2800.millis, 15, 30)
|
|
),
|
|
ThroughputAlert(
|
|
notificationGroup = DefaultNotificationGroup,
|
|
warnPredicate = TriggerIfAbove(70000),
|
|
criticalPredicate = TriggerIfAbove(80000)
|
|
),
|
|
EmptyResponseRateAlert(
|
|
notificationGroup = DefaultNotificationGroup,
|
|
warnPredicate = TriggerIfAbove(2),
|
|
criticalPredicate = TriggerIfAbove(3)
|
|
)
|
|
)
|
|
|
|
override val debugAccessPolicies: Set[AccessPolicy] = DefaultHomeMixerAccessPolicy
|
|
}
|