mirror of
https://github.com/twitter/the-algorithm.git
synced 2024-06-30 06:56:08 +02:00
93 lines
3.4 KiB
Scala
93 lines
3.4 KiB
Scala
|
package com.twitter.home_mixer.functional_component.side_effect
|
||
|
|
||
|
import com.twitter.eventbus.client.EventBusPublisher
|
||
|
import com.twitter.home_mixer.model.request.FollowingProduct
|
||
|
import com.twitter.home_mixer.model.request.ForYouProduct
|
||
|
import com.twitter.home_mixer.model.request.HasSeenTweetIds
|
||
|
import com.twitter.home_mixer.service.HomeMixerAlertConfig
|
||
|
import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect
|
||
|
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.impressionstore.thriftscala.Impression
|
||
|
import com.twitter.timelines.impressionstore.thriftscala.ImpressionList
|
||
|
import com.twitter.timelines.impressionstore.thriftscala.PublishedImpressionList
|
||
|
import com.twitter.timelines.impressionstore.thriftscala.SurfaceArea
|
||
|
import com.twitter.util.Time
|
||
|
import javax.inject.Inject
|
||
|
import javax.inject.Singleton
|
||
|
|
||
|
object PublishClientSentImpressionsEventBusSideEffect {
|
||
|
val HomeSurfaceArea: Option[Set[SurfaceArea]] = Some(Set(SurfaceArea.HomeTimeline))
|
||
|
val HomeLatestSurfaceArea: Option[Set[SurfaceArea]] = Some(Set(SurfaceArea.HomeLatestTimeline))
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Side effect that publishes seen tweet IDs sent from clients. The seen tweet IDs are sent to a
|
||
|
* heron topology which writes to a memcache dataset.
|
||
|
*/
|
||
|
@Singleton
|
||
|
class PublishClientSentImpressionsEventBusSideEffect @Inject() (
|
||
|
eventBusPublisher: EventBusPublisher[PublishedImpressionList])
|
||
|
extends PipelineResultSideEffect[PipelineQuery with HasSeenTweetIds, HasMarshalling]
|
||
|
with PipelineResultSideEffect.Conditionally[
|
||
|
PipelineQuery with HasSeenTweetIds,
|
||
|
HasMarshalling
|
||
|
] {
|
||
|
import PublishClientSentImpressionsEventBusSideEffect._
|
||
|
|
||
|
override val identifier: SideEffectIdentifier =
|
||
|
SideEffectIdentifier("PublishClientSentImpressionsEventBus")
|
||
|
|
||
|
override def onlyIf(
|
||
|
query: PipelineQuery with HasSeenTweetIds,
|
||
|
selectedCandidates: Seq[CandidateWithDetails],
|
||
|
remainingCandidates: Seq[CandidateWithDetails],
|
||
|
droppedCandidates: Seq[CandidateWithDetails],
|
||
|
response: HasMarshalling
|
||
|
): Boolean = query.seenTweetIds.exists(_.nonEmpty)
|
||
|
|
||
|
def buildEvents(
|
||
|
query: PipelineQuery with HasSeenTweetIds,
|
||
|
currentTime: Long
|
||
|
): Option[Seq[Impression]] = {
|
||
|
val surfaceArea = query.product match {
|
||
|
case ForYouProduct => HomeSurfaceArea
|
||
|
case FollowingProduct => HomeLatestSurfaceArea
|
||
|
case _ => None
|
||
|
}
|
||
|
query.seenTweetIds.map { seenTweetIds =>
|
||
|
seenTweetIds.map { tweetId =>
|
||
|
Impression(
|
||
|
tweetId = tweetId,
|
||
|
impressionTime = Some(currentTime),
|
||
|
surfaceAreas = surfaceArea
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
final override def apply(
|
||
|
inputs: PipelineResultSideEffect.Inputs[PipelineQuery with HasSeenTweetIds, HasMarshalling]
|
||
|
): Stitch[Unit] = {
|
||
|
val currentTime = Time.now.inMilliseconds
|
||
|
val impressions = buildEvents(inputs.query, currentTime)
|
||
|
|
||
|
Stitch.callFuture(
|
||
|
eventBusPublisher.publish(
|
||
|
PublishedImpressionList(
|
||
|
inputs.query.getRequiredUserId,
|
||
|
ImpressionList(impressions),
|
||
|
currentTime
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
}
|
||
|
|
||
|
override val alerts = Seq(
|
||
|
HomeMixerAlertConfig.BusinessHours.defaultSuccessRateAlert(99.4)
|
||
|
)
|
||
|
}
|