the-algorithm/home-mixer/server/src/main/scala/com/twitter/home_mixer/functional_component/gate/TimelinesPersistenceStoreLastInjectionGate.scala
twitter-team ef4c5eb65e Twitter Recommendation Algorithm
Please note we have force-pushed a new initial commit in order to remove some publicly-available Twitter user information. Note that this process may be required in the future.
2023-03-31 17:36:31 -05:00

52 lines
2.5 KiB
Scala

package com.twitter.home_mixer.functional_component.gate
import com.twitter.common_internal.analytics.twitter_client_user_agent_parser.UserAgent
import com.twitter.product_mixer.core.feature.Feature
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.timelinemixer.clients.persistence.TimelineResponseV3
import com.twitter.timelinemixer.injection.store.persistence.TimelinePersistenceUtils
import com.twitter.timelines.configapi.Param
import com.twitter.timelines.util.client_info.ClientPlatform
import com.twitter.timelineservice.model.rich.EntityIdType
import com.twitter.util.Duration
import com.twitter.util.Time
/**
* Gate used to reduce the frequency of injections. Note that the actual interval between injections may be
* less than the specified minInjectionIntervalParam if data is unavailable or missing. For example, being deleted by
* the persistence store via a TTL or similar mechanism.
*
* @param minInjectionIntervalParam the desired minimum interval between injections
* @param persistenceEntriesFeature the feature for retrieving persisted timeline responses
*/
case class TimelinesPersistenceStoreLastInjectionGate(
minInjectionIntervalParam: Param[Duration],
persistenceEntriesFeature: Feature[PipelineQuery, Seq[TimelineResponseV3]],
entityIdType: EntityIdType.Value)
extends Gate[PipelineQuery]
with TimelinePersistenceUtils {
override val identifier: GateIdentifier = GateIdentifier("TimelinesPersistenceStoreLastInjection")
override def shouldContinue(query: PipelineQuery): Stitch[Boolean] =
Stitch(
query.queryTime.since(getLastInjectionTime(query)) > query.params(minInjectionIntervalParam))
private def getLastInjectionTime(query: PipelineQuery) = query.features
.flatMap { featureMap =>
val timelineResponses = featureMap.getOrElse(persistenceEntriesFeature, Seq.empty)
val clientPlatform = ClientPlatform.fromQueryOptions(
clientAppId = query.clientContext.appId,
userAgent = query.clientContext.userAgent.flatMap(UserAgent.fromString)
)
val sortedResponses = responseByClient(clientPlatform, timelineResponses)
val latestResponseWithEntityIdTypeEntry =
sortedResponses.find(_.entries.exists(_.entityIdType == entityIdType))
latestResponseWithEntityIdTypeEntry.map(_.servedTime)
}.getOrElse(Time.Bottom)
}