def apply()

in tweetypie/server/src/main/scala/com/twitter/tweetypie/config/TweetServiceBuilder.scala [141:478]


  def apply(
    settings: TweetServiceSettings,
    statsReceiver: StatsReceiver,
    tweetServiceScope: StatsReceiver,
    syncTweetService: ThriftTweetService,
    timer: Timer,
    deciderGates: TweetypieDeciderGates,
    featureSwitchesWithExperiments: FeatureSwitches,
    featureSwitchesWithoutExperiments: FeatureSwitches,
    backendClients: BackendClients,
    clientIdHelper: ClientIdHelper,
  ): ThriftTweetService = {
    val (syncInvocationBuilder, asyncInvocationBuilder) = {
      val b =
        new ServiceInvocationBuilder(syncTweetService, settings.simulateDeferredrpcCallbacks)
      (b.withClientId(settings.thriftClientId), b.withClientId(settings.deferredrpcClientId))
    }

    val tweetKeyFactory = TweetKeyFactory(settings.tweetKeyCacheVersion)

    val caches =
      if (!settings.withCache)
        Caches.NoCache
      else
        Caches(
          settings = settings,
          stats = statsReceiver,
          timer = timer,
          clients = backendClients,
          tweetKeyFactory = tweetKeyFactory,
          deciderGates = deciderGates,
          clientIdHelper = clientIdHelper,
        )

    val logicalRepos =
      LogicalRepositories(
        settings = settings,
        stats = statsReceiver,
        timer = timer,
        deciderGates = deciderGates,
        external = new ExternalServiceRepositories(
          clients = backendClients,
          statsReceiver = statsReceiver,
          settings = settings,
          clientIdHelper = clientIdHelper,
        ),
        caches = caches,
        stratoClient = backendClients.stratoserverClient,
        hasMedia = hasMedia,
        clientIdHelper = clientIdHelper,
        featureSwitchesWithoutExperiments = featureSwitchesWithoutExperiments,
      )

    val tweetCreationLock =
      new CacheBasedTweetCreationLock(
        cache = caches.tweetCreateLockerCache,
        maxTries = 3,
        stats = statsReceiver.scope("tweet_save").scope("locker"),
        logUniquenessId =
          if (settings.scribeUniquenessIds) CacheBasedTweetCreationLock.ScribeUniquenessId
          else CacheBasedTweetCreationLock.LogUniquenessId
      )

    val tweetStores =
      TweetStores(
        settings = settings,
        statsReceiver = statsReceiver,
        timer = timer,
        deciderGates = deciderGates,
        tweetKeyFactory = tweetKeyFactory,
        clients = backendClients,
        caches = caches,
        asyncBuilder = asyncInvocationBuilder,
        hasMedia = hasMedia,
        clientIdHelper = clientIdHelper,
      )

    val tweetDeletePathHandler =
      new DefaultTweetDeletePathHandler(
        tweetServiceScope,
        logicalRepos.tweetResultRepo,
        logicalRepos.optionalUserRepo,
        logicalRepos.stratoSafetyLabelsRepo,
        logicalRepos.lastQuoteOfQuoterRepo,
        tweetStores,
        getPerspectives = backendClients.timelineService.getPerspectives,
      )

    val tweetBuilders =
      TweetBuilders(
        settings = settings,
        statsReceiver = statsReceiver,
        deciderGates = deciderGates,
        featureSwitchesWithExperiments = featureSwitchesWithExperiments,
        clients = backendClients,
        caches = caches,
        repos = logicalRepos,
        tweetStore = tweetStores,
        hasMedia = hasMedia,
        unretweetEdits = tweetDeletePathHandler.unretweetEdits,
      )

    val hydrateTweetForInsert =
      WritePathHydration.hydrateTweet(
        logicalRepos.tweetHydrators.hydrator,
        statsReceiver.scope("insert_tweet")
      )

    val defaultTweetQueryOptions = TweetQuery.Options(include = GetTweetsHandler.BaseInclude)

    val parentUserIdRepo: ParentUserIdRepository.Type =
      ParentUserIdRepository(
        tweetRepo = logicalRepos.tweetRepo
      )

    val undeleteTweetHandler =
      UndeleteTweetHandlerBuilder(
        backendClients.tweetStorageClient,
        logicalRepos,
        tweetStores,
        parentUserIdRepo,
        statsReceiver
      )

    val eraseUserTweetsHandler =
      EraseUserTweetsHandlerBuilder(
        backendClients,
        asyncInvocationBuilder,
        deciderGates,
        settings,
        timer,
        tweetDeletePathHandler,
        tweetServiceScope
      )

    val setRetweetVisibilityHandler =
      SetRetweetVisibilityHandler(
        tweetGetter =
          TweetRepository.tweetGetter(logicalRepos.optionalTweetRepo, defaultTweetQueryOptions),
        tweetStores.setRetweetVisibility
      )

    val takedownHandler =
      TakedownHandlerBuilder(
        logicalRepos = logicalRepos,
        tweetStores = tweetStores
      )

    val updatePossiblySensitiveTweetHandler =
      UpdatePossiblySensitiveTweetHandler(
        HandlerError.getRequired(
          TweetRepository.tweetGetter(logicalRepos.optionalTweetRepo, defaultTweetQueryOptions),
          HandlerError.tweetNotFoundException
        ),
        HandlerError.getRequired(
          FutureArrow(
            UserRepository
              .userGetter(
                logicalRepos.optionalUserRepo,
                UserQueryOptions(Set(UserField.Safety), UserVisibility.All)
              )
              .compose(UserKey.byId)
          ),
          HandlerError.userNotFoundException
        ),
        tweetStores.updatePossiblySensitiveTweet
      )

    val userTakedownHandler =
      UserTakedownHandlerBuilder(
        logicalRepos = logicalRepos,
        tweetStores = tweetStores,
        stats = tweetServiceScope
      )

    val getDeletedTweetsHandler =
      GetDeletedTweetsHandler(
        getDeletedTweets = backendClients.tweetStorageClient.getDeletedTweets,
        tweetsExist =
          GetDeletedTweetsHandler.tweetsExist(backendClients.tweetStorageClient.getTweet),
        stats = tweetServiceScope.scope("get_deleted_tweets_handler")
      )

    val hydrateQuotedTweet =
      WritePathHydration.hydrateQuotedTweet(
        logicalRepos.optionalTweetRepo,
        logicalRepos.optionalUserRepo,
        logicalRepos.quoterHasAlreadyQuotedRepo
      )

    val deleteLocationDataHandler =
      DeleteLocationDataHandler(
        backendClients.geoScrubEventStore.getGeoScrubTimestamp,
        Scribe(DeleteLocationData, "tweetypie_delete_location_data"),
        backendClients.deleteLocationDataPublisher
      )

    val getStoredTweetsHandler = GetStoredTweetsHandler(logicalRepos.tweetResultRepo)

    val getStoredTweetsByUserHandler = GetStoredTweetsByUserHandler(
      getStoredTweetsHandler = getStoredTweetsHandler,
      getStoredTweet = backendClients.tweetStorageClient.getStoredTweet,
      selectPage = FutureArrow { select =>
        backendClients.tflockReadClient
          .selectPage(select, Some(settings.getStoredTweetsByUserPageSize))
      },
      maxPages = settings.getStoredTweetsByUserMaxPages
    )

    val getTweetsHandler =
      GetTweetsHandler(
        logicalRepos.tweetResultRepo,
        logicalRepos.containerAsGetTweetResultRepo,
        logicalRepos.deletedTweetVisibilityRepo,
        statsReceiver.scope("read_path"),
        deciderGates.shouldMaterializeContainers
      )

    val getTweetFieldsHandler =
      GetTweetFieldsHandler(
        logicalRepos.tweetResultRepo,
        logicalRepos.deletedTweetVisibilityRepo,
        logicalRepos.containerAsGetTweetFieldsResultRepo,
        statsReceiver.scope("read_path"),
        deciderGates.shouldMaterializeContainers
      )

    val unretweetHandler =
      UnretweetHandler(
        tweetDeletePathHandler.deleteTweets,
        backendClients.timelineService.getPerspectives,
        tweetDeletePathHandler.unretweetEdits,
        logicalRepos.tweetRepo,
      )

    val hydrateInsertEvent =
      WritePathHydration.hydrateInsertTweetEvent(
        hydrateTweet = hydrateTweetForInsert,
        hydrateQuotedTweet = hydrateQuotedTweet
      )

    val scrubGeoUpdateUserTimestampBuilder =
      ScrubGeoEventBuilder.UpdateUserTimestamp(
        stats = tweetServiceScope.scope("scrub_geo_update_user_timestamp"),
        userRepo = logicalRepos.optionalUserRepo
      )

    val scrubGeoScrubTweetsBuilder =
      ScrubGeoEventBuilder.ScrubTweets(
        stats = tweetServiceScope.scope("scrub_geo"),
        userRepo = logicalRepos.optionalUserRepo
      )

    val handlerFilter =
      PostTweet
        .DuplicateHandler(
          tweetCreationLock = tweetCreationLock,
          getTweets = getTweetsHandler,
          stats = statsReceiver.scope("duplicate")
        )
        .andThen(PostTweet.RescueTweetCreateFailure)
        .andThen(PostTweet.LogFailures)

    val postTweetHandler =
      handlerFilter[PostTweetRequest](
        PostTweet.Handler(
          tweetBuilder = tweetBuilders.tweetBuilder,
          hydrateInsertEvent = hydrateInsertEvent,
          tweetStore = tweetStores,
        )
      )

    val postRetweetHandler =
      handlerFilter[RetweetRequest](
        PostTweet.Handler(
          tweetBuilder = tweetBuilders.retweetBuilder,
          hydrateInsertEvent = hydrateInsertEvent,
          tweetStore = tweetStores,
        )
      )

    val quotedTweetDeleteBuilder: QuotedTweetDeleteEventBuilder.Type =
      QuotedTweetDeleteEventBuilder(logicalRepos.optionalTweetRepo)

    val quotedTweetTakedownBuilder: QuotedTweetTakedownEventBuilder.Type =
      QuotedTweetTakedownEventBuilder(logicalRepos.optionalTweetRepo)

    val setAdditionalFieldsBuilder: SetAdditionalFieldsBuilder.Type =
      SetAdditionalFieldsBuilder(
        tweetRepo = logicalRepos.tweetRepo
      )

    val asyncSetAdditionalFieldsBuilder: AsyncSetAdditionalFieldsBuilder.Type =
      AsyncSetAdditionalFieldsBuilder(
        userRepo = logicalRepos.userRepo
      )

    val deleteAdditionalFieldsBuilder: DeleteAdditionalFieldsBuilder.Type =
      DeleteAdditionalFieldsBuilder(
        tweetRepo = logicalRepos.tweetRepo
      )

    val asyncDeleteAdditionalFieldsBuilder: AsyncDeleteAdditionalFieldsBuilder.Type =
      AsyncDeleteAdditionalFieldsBuilder(
        userRepo = logicalRepos.userRepo
      )

    new DispatchingTweetService(
      asyncDeleteAdditionalFieldsBuilder = asyncDeleteAdditionalFieldsBuilder,
      asyncSetAdditionalFieldsBuilder = asyncSetAdditionalFieldsBuilder,
      deleteAdditionalFieldsBuilder = deleteAdditionalFieldsBuilder,
      deleteLocationDataHandler = deleteLocationDataHandler,
      deletePathHandler = tweetDeletePathHandler,
      eraseUserTweetsHandler = eraseUserTweetsHandler,
      getDeletedTweetsHandler = getDeletedTweetsHandler,
      getStoredTweetsHandler = getStoredTweetsHandler,
      getStoredTweetsByUserHandler = getStoredTweetsByUserHandler,
      getTweetsHandler = getTweetsHandler,
      getTweetFieldsHandler = getTweetFieldsHandler,
      getTweetCountsHandler = GetTweetCountsHandler(logicalRepos.tweetCountsRepo),
      postTweetHandler = postTweetHandler,
      postRetweetHandler = postRetweetHandler,
      quotedTweetDeleteBuilder = quotedTweetDeleteBuilder,
      quotedTweetTakedownBuilder = quotedTweetTakedownBuilder,
      scrubGeoUpdateUserTimestampBuilder = scrubGeoUpdateUserTimestampBuilder,
      scrubGeoScrubTweetsBuilder = scrubGeoScrubTweetsBuilder,
      setAdditionalFieldsBuilder = setAdditionalFieldsBuilder,
      setRetweetVisibilityHandler = setRetweetVisibilityHandler,
      statsReceiver = statsReceiver,
      takedownHandler = takedownHandler,
      tweetStore = tweetStores,
      undeleteTweetHandler = undeleteTweetHandler,
      unretweetHandler = unretweetHandler,
      updatePossiblySensitiveTweetHandler = updatePossiblySensitiveTweetHandler,
      userTakedownHandler = userTakedownHandler,
      clientIdHelper = clientIdHelper,
    )
  }