Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 55 additions & 62 deletions src/main/java/org/prebid/server/auction/BidResponseCreator.java
Comment thread
AntoxaAntoxic marked this conversation as resolved.
Comment thread
AntoxaAntoxic marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
import org.prebid.server.settings.model.AccountAnalyticsConfig;
import org.prebid.server.settings.model.AccountAuctionConfig;
import org.prebid.server.settings.model.AccountAuctionEventConfig;
import org.prebid.server.settings.model.AccountBidRankingConfig;
import org.prebid.server.settings.model.AccountEventsConfig;
import org.prebid.server.settings.model.AccountTargetingConfig;
import org.prebid.server.settings.model.VideoStoredDataResult;
Expand All @@ -124,6 +125,7 @@
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class BidResponseCreator {
Expand Down Expand Up @@ -643,8 +645,11 @@ private Future<BidResponse> cacheBidsAndCreateResponse(List<BidderResponseInfo>

final ExtRequestTargeting targeting = targeting(bidRequest);

final List<BidderResponseInfo> bidderResponseInfos = toBidderResponseWithTargetingBidInfos(
bidderResponses, bidderToMultiBids, preferDeals(targeting));
final List<BidderResponseInfo> bidderResponseInfos = injectWithTargetingAndBidRanking(
bidderResponses,
bidderToMultiBids,
preferDeals(targeting),
isBidRankingEnabled(auctionContext.getAccount()));

final Set<BidInfo> bidInfos = bidderResponseInfos.stream()
.map(BidderResponseInfo::getSeatBid)
Expand Down Expand Up @@ -682,45 +687,58 @@ private static boolean preferDeals(ExtRequestTargeting targeting) {
return BooleanUtils.toBooleanDefaultIfNull(targeting != null ? targeting.getPreferdeals() : null, false);
}

private List<BidderResponseInfo> toBidderResponseWithTargetingBidInfos(
private static boolean isBidRankingEnabled(Account account) {
return Optional.ofNullable(account.getAuction())
.map(AccountAuctionConfig::getRanking)
.map(AccountBidRankingConfig::getEnabled)
.orElse(false);
}

private List<BidderResponseInfo> injectWithTargetingAndBidRanking(
List<BidderResponseInfo> bidderResponses,
Map<String, MultiBidConfig> bidderToMultiBids,
boolean preferDeals) {
boolean preferDeals,
boolean isBidRankingEnabled) {

final Map<BidderResponseInfo, List<BidInfo>> bidderResponseToReducedBidInfos = bidderResponses.stream()
.collect(Collectors.toMap(
Function.identity(),
bidderResponse -> toSortedMultiBidInfo(bidderResponse, bidderToMultiBids, preferDeals)));

final Map<String, Map<String, List<BidInfo>>> impIdToBidderToBidInfos = bidderResponseToReducedBidInfos.values()
final Map<String, List<BidInfo>> impIdToBidInfos = bidderResponseToReducedBidInfos.values()
.stream()
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(
bidInfo -> bidInfo.getCorrespondingImp().getId(),
Collectors.groupingBy(BidInfo::getBidder)));
Collectors.collectingAndThen(Collectors.toList(), bidInfos -> bidInfos.stream()
.sorted(winningBidComparatorFactory.create(preferDeals).reversed())
.toList())));

// Best bids from bidders for imp
final Set<BidInfo> winningBids = new HashSet<>();
// All bids from bidder for imp
final Set<BidInfo> winningBidsByBidder = new HashSet<>();

for (final Map<String, List<BidInfo>> bidderToBidInfos : impIdToBidderToBidInfos.values()) {

bidderToBidInfos.values().forEach(winningBidsByBidder::addAll);

bidderToBidInfos.values().stream()
.flatMap(Collection::stream)
.max(winningBidComparatorFactory.create(preferDeals))
.ifPresent(winningBids::add);
final Map<String, Map<String, List<BidInfo>>> seatToBidderToBids = new HashMap<>();

for (final List<BidInfo> bidInfos : impIdToBidInfos.values()) {
final List<BidInfo> bidsWithRanking = isBidRankingEnabled
? IntStream.range(0, bidInfos.size())
.mapToObj(i -> bidInfos.get(i).toBuilder().rank(i + 1).build())
.toList()
: bidInfos;

if (!bidsWithRanking.isEmpty()) {
winningBids.add(bidsWithRanking.getFirst());
bidsWithRanking.forEach(bidInfo ->
seatToBidderToBids.computeIfAbsent(bidInfo.getSeat(), k -> new HashMap<>())
.computeIfAbsent(bidInfo.getBidder(), k -> new ArrayList<>()).add(bidInfo));
}
}

return bidderResponseToReducedBidInfos.entrySet().stream()
.map(responseToBidInfos -> injectBidInfoWithTargeting(
responseToBidInfos.getKey(),
responseToBidInfos.getValue(),
return bidderResponseToReducedBidInfos.keySet().stream()
.map(bidderResponseInfo -> injectBidInfoWithTargeting(
bidderResponseInfo,
bidderToMultiBids,
winningBids,
winningBidsByBidder))
seatToBidderToBids.getOrDefault(bidderResponseInfo.getSeat(), Collections.emptyMap())
.getOrDefault(bidderResponseInfo.getBidder(), Collections.emptyList()),
winningBids))
.toList();
}

Expand Down Expand Up @@ -749,14 +767,16 @@ private List<BidInfo> sortReducedBidInfo(List<BidInfo> bidInfos, int limit, bool
}

private static BidderResponseInfo injectBidInfoWithTargeting(BidderResponseInfo bidderResponseInfo,
List<BidInfo> bidderBidInfos,
Map<String, MultiBidConfig> bidderToMultiBids,
Set<BidInfo> winningBids,
Set<BidInfo> winningBidsByBidder) {
List<BidInfo> bidderBidInfos,
Set<BidInfo> winningBids) {

final String bidder = bidderResponseInfo.getBidder();
final List<BidInfo> bidInfosWithTargeting = toBidInfoWithTargeting(bidderBidInfos, bidder, bidderToMultiBids,
winningBids, winningBidsByBidder);
final List<BidInfo> bidInfosWithTargeting = toBidInfoWithTargeting(
bidderBidInfos,
bidder,
bidderToMultiBids,
winningBids);

final BidderSeatBidInfo seatBid = bidderResponseInfo.getSeatBid();
final BidderSeatBidInfo modifiedSeatBid = seatBid.with(bidInfosWithTargeting);
Expand All @@ -766,23 +786,21 @@ private static BidderResponseInfo injectBidInfoWithTargeting(BidderResponseInfo
private static List<BidInfo> toBidInfoWithTargeting(List<BidInfo> bidderBidInfos,
String bidder,
Map<String, MultiBidConfig> bidderToMultiBids,
Set<BidInfo> winningBids,
Set<BidInfo> winningBidsByBidder) {
Set<BidInfo> winningBids) {

final Map<String, List<BidInfo>> impIdToBidInfos = bidderBidInfos.stream()
.collect(Collectors.groupingBy(bidInfo -> bidInfo.getCorrespondingImp().getId()));

return impIdToBidInfos.values().stream()
.map(bidInfos -> injectTargeting(bidInfos, bidder, bidderToMultiBids, winningBids, winningBidsByBidder))
.map(bidInfos -> injectTargeting(bidInfos, bidder, bidderToMultiBids, winningBids))
.flatMap(Collection::stream)
.toList();
}

private static List<BidInfo> injectTargeting(List<BidInfo> bidderImpIdBidInfos,
String bidder,
Map<String, MultiBidConfig> bidderToMultiBids,
Set<BidInfo> winningBids,
Set<BidInfo> winningBidsByBidder) {
Set<BidInfo> winningBids) {

final List<BidInfo> result = new ArrayList<>();

Expand All @@ -797,7 +815,6 @@ private static List<BidInfo> injectTargeting(List<BidInfo> bidderImpIdBidInfos,

final TargetingInfo targetingInfo = TargetingInfo.builder()
.isTargetingEnabled(targetingBidderCode != null)
.isBidderWinningBid(winningBidsByBidder.contains(bidInfo))
.isWinningBid(winningBids.contains(bidInfo))
.isAddTargetBidderCode(targetingBidderCode != null && multiBidSize > 1)
.bidderCode(targetingBidderCode)
Expand All @@ -812,17 +829,9 @@ private static List<BidInfo> injectTargeting(List<BidInfo> bidderImpIdBidInfos,
}

private static String targetingCode(String base, String prefix, int i) {
if (i == 0) {
return base;
}

return prefix != null ? prefix + (i + 1) : null;
return i == 0 ? base : prefix != null ? prefix + (i + 1) : null;
Comment thread
AntoxaAntoxic marked this conversation as resolved.
Outdated
}

/**
* Returns {@link ExtBidResponse} object, populated with response time, errors and debug info (if requested)
* from all bidders.
*/
private ExtBidResponse toExtBidResponse(List<BidderResponseInfo> bidderResponseInfos,
AuctionContext auctionContext,
CacheServiceResult cacheResult,
Expand Down Expand Up @@ -1544,6 +1553,7 @@ private Bid toBid(BidInfo bidInfo,
BidRequest bidRequest,
Account account,
Map<String, List<ExtBidderError>> bidWarnings) {

final TargetingInfo targetingInfo = bidInfo.getTargetingInfo();
final BidType bidType = bidInfo.getBidType();
final Bid bid = bidInfo.getBid();
Expand Down Expand Up @@ -1584,6 +1594,7 @@ private Bid toBid(BidInfo bidInfo,
.dealTierSatisfied(dealsTierSatisfied)
.cache(cache)
.passThrough(extractPassThrough(bidInfo.getCorrespondingImp()))
.rank(bidInfo.getRank())
.build();

final ObjectNode updatedBidExt =
Expand All @@ -1601,7 +1612,6 @@ private Bid toBid(BidInfo bidInfo,
private boolean shouldIncludeTargetingInResponse(ExtRequestTargeting targeting, TargetingInfo targetingInfo) {
return targeting != null
&& targetingInfo.isTargetingEnabled()
&& targetingInfo.isBidderWinningBid()
&& (Objects.equals(targeting.getIncludebidderkeys(), true)
|| Objects.equals(targeting.getIncludewinners(), true)
|| Objects.equals(targeting.getIncludeformat(), true));
Expand Down Expand Up @@ -1740,9 +1750,6 @@ private static boolean eventsAllowedByRequest(AuctionContext auctionContext) {
return prebid != null && prebid.getEvents() != null;
}

/**
* Extracts auction timestamp from {@link ExtRequest} or get it from {@link Clock} if it is null.
*/
private long auctionTimestamp(AuctionContext auctionContext) {
final ExtRequest ext = auctionContext.getBidRequest().getExt();
final ExtRequestPrebid prebid = ext != null ? ext.getPrebid() : null;
Expand Down Expand Up @@ -1872,9 +1879,6 @@ private TargetingKeywordsCreator createKeywordsCreator(ExtRequestTargeting targe
resolveKeyPrefix);
}

/**
* Returns max targeting keyword length.
*/
private int resolveTruncateAttrChars(ExtRequestTargeting targeting, Account account) {
final AccountAuctionConfig accountAuctionConfig = account.getAuction();
final Integer accountTruncateTargetAttr =
Expand Down Expand Up @@ -1929,11 +1933,6 @@ private static boolean isCachedDebugEnabled(CachedDebugLog cachedDebugLog) {
return cachedDebugLog != null && cachedDebugLog.isEnabled();
}

/**
* Parse {@link JsonNode} to {@link List} of {@link ExtPriceGranularity}.
* <p>
* Throws {@link PreBidException} in case of errors during decoding price granularity.
*/
private ExtPriceGranularity parsePriceGranularity(JsonNode priceGranularity) {
try {
return mapper.mapper().treeToValue(priceGranularity, ExtPriceGranularity.class);
Expand Down Expand Up @@ -1969,9 +1968,6 @@ private static BidResponse populateSeatNonBid(AuctionContext auctionContext, Bid
return bidResponse.toBuilder().ext(updatedExtBidResponse).build();
}

/**
* Creates {@link CacheAsset} for the given cache ID.
*/
private CacheAsset toCacheAsset(String cacheId) {
return CacheAsset.of(cacheAssetUrlTemplate.concat(cacheId), cacheId);
}
Expand All @@ -1983,9 +1979,6 @@ private static <T> Set<T> nullIfEmpty(Set<T> set) {
return Collections.unmodifiableSet(set);
}

/**
* Creates {@link ExtBidPrebidVideo} from bid extension.
*/
private Optional<ExtBidPrebidVideo> getExtBidPrebidVideo(ObjectNode bidExt) {
return getExtPrebid(bidExt, ExtBidPrebid.class)
.map(ExtBidPrebid::getVideo);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/prebid/server/auction/model/BidInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public class BidInfo {

Integer vastTtl;

Integer rank;

public String getBidId() {
final ObjectNode extNode = bid != null ? bid.getExt() : null;
final JsonNode bidIdNode = extNode != null ? extNode.path("prebid").path("bidid") : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ public class TargetingInfo {

boolean isWinningBid;

boolean isBidderWinningBid;

boolean isAddTargetBidderCode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ public class ExtBidPrebid {

@JsonProperty("passthrough")
JsonNode passThrough;

Integer rank;
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ public class AccountAuctionConfig {
PaaFormat paaFormat;

AccountCacheConfig cache;

AccountBidRankingConfig ranking;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.prebid.server.settings.model;

import lombok.Value;

@Value(staticConstructor = "of")
public class AccountBidRankingConfig {

Boolean enabled;
}
Loading
Loading