mirror of
https://github.com/twitter/the-algorithm.git
synced 2024-06-30 06:56:08 +02:00
69 lines
3.1 KiB
Scala
69 lines
3.1 KiB
Scala
|
package com.twitter.home_mixer.functional_component.side_effect
|
||
|
|
||
|
import com.twitter.home_mixer.model.HomeFeatures.PersistenceEntriesFeature
|
||
|
import com.twitter.home_mixer.model.request.FollowingProduct
|
||
|
import com.twitter.home_mixer.model.request.ForYouProduct
|
||
|
import com.twitter.home_mixer.param.HomeGlobalParams.TimelinesPersistenceStoreMaxEntriesPerClient
|
||
|
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.marshalling.response.urt.Timeline
|
||
|
import com.twitter.product_mixer.core.pipeline.PipelineQuery
|
||
|
import com.twitter.stitch.Stitch
|
||
|
import com.twitter.timelinemixer.clients.persistence.TimelineResponseBatchesClient
|
||
|
import com.twitter.timelinemixer.clients.persistence.TimelineResponseV3
|
||
|
import com.twitter.timelineservice.model.TimelineQuery
|
||
|
import com.twitter.timelineservice.model.core.TimelineKind
|
||
|
import javax.inject.Inject
|
||
|
import javax.inject.Singleton
|
||
|
|
||
|
/**
|
||
|
* Side effect that truncates entries in the Timelines Persistence store
|
||
|
* based on the number of entries per client.
|
||
|
*/
|
||
|
@Singleton
|
||
|
class TruncateTimelinesPersistenceStoreSideEffect @Inject() (
|
||
|
timelineResponseBatchesClient: TimelineResponseBatchesClient[TimelineResponseV3])
|
||
|
extends PipelineResultSideEffect[PipelineQuery, Timeline] {
|
||
|
|
||
|
override val identifier: SideEffectIdentifier =
|
||
|
SideEffectIdentifier("TruncateTimelinesPersistenceStore")
|
||
|
|
||
|
def getResponsesToDelete(query: PipelineQuery): Seq[TimelineResponseV3] = {
|
||
|
val responses =
|
||
|
query.features.map(_.getOrElse(PersistenceEntriesFeature, Seq.empty)).toSeq.flatten
|
||
|
val responsesByClient = responses.groupBy(_.clientPlatform).values.toSeq
|
||
|
val maxEntriesPerClient = query.params(TimelinesPersistenceStoreMaxEntriesPerClient)
|
||
|
|
||
|
responsesByClient.flatMap {
|
||
|
_.sortBy(_.servedTime.inMilliseconds)
|
||
|
.foldRight((Seq.empty[TimelineResponseV3], maxEntriesPerClient)) {
|
||
|
case (response, (responsesToDelete, remainingCap)) =>
|
||
|
if (remainingCap > 0) (responsesToDelete, remainingCap - response.entries.size)
|
||
|
else (response +: responsesToDelete, remainingCap)
|
||
|
} match { case (responsesToDelete, _) => responsesToDelete }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
final override def apply(
|
||
|
inputs: PipelineResultSideEffect.Inputs[PipelineQuery, Timeline]
|
||
|
): Stitch[Unit] = {
|
||
|
val timelineKind = inputs.query.product match {
|
||
|
case FollowingProduct => TimelineKind.homeLatest
|
||
|
case ForYouProduct => TimelineKind.home
|
||
|
case other => throw new UnsupportedOperationException(s"Unknown product: $other")
|
||
|
}
|
||
|
val timelineQuery = TimelineQuery(id = inputs.query.getRequiredUserId, kind = timelineKind)
|
||
|
|
||
|
val responsesToDelete = getResponsesToDelete(inputs.query)
|
||
|
|
||
|
if (responsesToDelete.nonEmpty)
|
||
|
Stitch.callFuture(timelineResponseBatchesClient.delete(timelineQuery, responsesToDelete))
|
||
|
else Stitch.Unit
|
||
|
}
|
||
|
|
||
|
override val alerts = Seq(
|
||
|
HomeMixerAlertConfig.BusinessHours.defaultSuccessRateAlert(99.8)
|
||
|
)
|
||
|
}
|