Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add category mapping enabled toggle #1565

Merged
merged 3 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions docs/config-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Removes and downloads file again if depending service cant process probably corr
- `auction.validations.banner-creative-max-size` - enables creative max size validation for banners. Possible values: `skip`, `enforce`, `warn`. Default is `skip`.
- `auction.validations.secure-markup` - enables secure markup validation. Possible values: `skip`, `enforce`, `warn`. Default is `skip`.
- `auction.host-schain-node` - defines global schain node that will be appended to `request.source.ext.schain.nodes` passed to bidders
- `auction.category-mapping-enabled` - if equals to `true` the category mapping feature will be active while auction.

## Event
- `event.default-timeout-ms` - timeout for event notifications
Expand Down
178 changes: 97 additions & 81 deletions src/main/java/org/prebid/server/auction/BidResponseCreator.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,15 @@ public CategoryMappingService(ApplicationSettings applicationSettings, JacksonMa
*/
public Future<CategoryMappingResult> createCategoryMapping(List<BidderResponse> bidderResponses,
BidRequest bidRequest,
ExtRequestTargeting targeting,
Timeout timeout) {

final ExtRequestTargeting targeting = targeting(bidRequest);

final ExtIncludeBrandCategory includeBrandCategory = ObjectUtil.getIfNotNull(
targeting, ExtRequestTargeting::getIncludebrandcategory);

if (includeBrandCategory == null) {
return Future.succeededFuture(
CategoryMappingResult.of(
Collections.emptyMap(),
Collections.emptyMap(),
bidderResponses,
Collections.emptyList()));
return Future.succeededFuture(CategoryMappingResult.of(bidderResponses));
}

final boolean withCategory = BooleanUtils.toBooleanDefaultIfNull(
Expand All @@ -116,6 +112,12 @@ public Future<CategoryMappingResult> createCategoryMapping(List<BidderResponse>
bidderResponses, categoryBidContexts, bidRequest, targeting, withCategory, rejectedBids));
}

private static ExtRequestTargeting targeting(BidRequest bidRequest) {
final ExtRequest ext = bidRequest.getExt();
final ExtRequestPrebid prebid = ext != null ? ext.getPrebid() : null;
return prebid != null ? prebid.getTargeting() : null;
}

/**
* Converts integer ad server to string representation or throws exception if unknown.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class VideoStoredRequestProcessor {
private VideoStoredRequestProcessor(boolean enforceStoredRequest,
List<String> blacklistedAccounts,
long defaultTimeout,
String adServerCurrency,
String currency,
BidRequest defaultBidRequest,
ApplicationSettings applicationSettings,
VideoRequestValidator validator,
Expand All @@ -87,7 +87,7 @@ private VideoStoredRequestProcessor(boolean enforceStoredRequest,
this.enforceStoredRequest = enforceStoredRequest;
this.blacklistedAccounts = blacklistedAccounts;
this.defaultTimeout = defaultTimeout;
this.currency = StringUtils.isBlank(adServerCurrency) ? DEFAULT_CURRENCY : adServerCurrency;
this.currency = currency;
this.defaultBidRequest = defaultBidRequest;
this.applicationSettings = applicationSettings;
this.validator = validator;
Expand Down Expand Up @@ -116,7 +116,7 @@ public static VideoStoredRequestProcessor create(boolean enforceStoredRequest,
enforceStoredRequest,
Objects.requireNonNull(blacklistedAccounts),
defaultTimeout,
adServerCurrency,
StringUtils.isBlank(adServerCurrency) ? DEFAULT_CURRENCY : adServerCurrency,
readBidRequest(
defaultBidRequestPath, Objects.requireNonNull(fileSystem), Objects.requireNonNull(mapper)),
Objects.requireNonNull(applicationSettings),
Expand All @@ -137,39 +137,44 @@ public Future<WithPodErrors<BidRequest>> processVideoRequest(String accountId,
BidRequestVideo videoRequest) {

final Set<String> storedRequestIds = StringUtils.isNotBlank(storedBidRequestId)
? Collections.singleton(storedBidRequestId)
: Collections.emptySet();
? Collections.singleton(storedBidRequestId)
: Collections.emptySet();

return applicationSettings.getVideoStoredData(accountId, storedRequestIds, podIds,
timeoutFactory.create(defaultTimeout))
.compose(storedDataResult -> updateMetrics(storedDataResult, storedRequestIds, podIds))
.map(storedData -> mergeToBidRequest(storedData, videoRequest, storedBidRequestId))

.map(storedDataResult -> updateMetrics(storedDataResult, storedRequestIds, podIds))

.map(storedData -> toBidRequestWithPodErrors(storedData, videoRequest, storedBidRequestId))

.recover(exception -> Future.failedFuture(new InvalidRequestException(
String.format("Stored request fetching failed: %s", exception.getMessage()))));
}

private static BidRequest readBidRequest(String defaultBidRequestPath, FileSystem fileSystem,
private static BidRequest readBidRequest(String defaultBidRequestPath,
FileSystem fileSystem,
JacksonMapper mapper) {

return StringUtils.isNotBlank(defaultBidRequestPath)
? mapper.decodeValue(fileSystem.readFileBlocking(defaultBidRequestPath), BidRequest.class)
: null;
? mapper.decodeValue(fileSystem.readFileBlocking(defaultBidRequestPath), BidRequest.class)
: null;
}

private Future<StoredDataResult> updateMetrics(StoredDataResult storedDataResult,
Set<String> requestIds,
Set<String> impIds) {
private StoredDataResult updateMetrics(StoredDataResult storedDataResult,
Set<String> requestIds,
Set<String> impIds) {

requestIds.forEach(
id -> metrics.updateStoredRequestMetric(storedDataResult.getStoredIdToRequest().containsKey(id)));
impIds.forEach(
id -> metrics.updateStoredImpsMetric(storedDataResult.getStoredIdToImp().containsKey(id)));

return Future.succeededFuture(storedDataResult);
return storedDataResult;
}

private WithPodErrors<BidRequest> mergeToBidRequest(StoredDataResult storedResult,
BidRequestVideo videoRequest,
String storedBidRequestId) {
private WithPodErrors<BidRequest> toBidRequestWithPodErrors(StoredDataResult storedResult,
BidRequestVideo videoRequest,
String storedBidRequestId) {

final BidRequestVideo mergedStoredRequest = mergeBidRequest(videoRequest, storedBidRequestId, storedResult);
validator.validateStoredBidRequest(mergedStoredRequest, enforceStoredRequest, blacklistedAccounts);
Expand All @@ -194,8 +199,8 @@ private BidRequestVideo mergeBidRequest(BidRequestVideo originalRequest,
}

return StringUtils.isNotBlank(storedRequest)
? jsonMerger.merge(originalRequest, storedRequest, storedRequestId, BidRequestVideo.class)
: originalRequest;
? jsonMerger.merge(originalRequest, storedRequest, storedRequestId, BidRequestVideo.class)
: originalRequest;
}

private WithPodErrors<List<Imp>> mergeStoredImps(Podconfig podconfig,
Expand Down Expand Up @@ -306,28 +311,27 @@ private static Video updateVideo(Video video, Integer minDuration, Integer maxDu

private BidRequest mergeWithDefaultBidRequest(BidRequestVideo videoRequest, List<Imp> imps) {
final BidRequest.BidRequestBuilder bidRequestBuilder = defaultBidRequest != null
? defaultBidRequest.toBuilder()
: BidRequest.builder();
? defaultBidRequest.toBuilder()
: BidRequest.builder();

final Site site = videoRequest.getSite();
if (site != null) {
final Site.SiteBuilder siteBuilder = site.toBuilder();
final Content content = videoRequest.getContent();
if (content != null) {
siteBuilder.content(content);
bidRequestBuilder.site(site.toBuilder()
.content(content)
.build());
}
siteBuilder.content(content);
bidRequestBuilder.site(siteBuilder.build());
}

final App app = videoRequest.getApp();
if (app != null) {
final App.AppBuilder appBuilder = app.toBuilder();
final Content content = videoRequest.getContent();
if (content != null) {
appBuilder.content(content);
bidRequestBuilder.app(app.toBuilder()
.content(content)
.build());
}
bidRequestBuilder.app(appBuilder.build());
}

final Device device = videoRequest.getDevice();
Expand Down Expand Up @@ -355,8 +359,8 @@ private BidRequest mergeWithDefaultBidRequest(BidRequestVideo videoRequest, List
bidRequestBuilder.regs(regs);
}

final Long videoTmax = timeoutResolver.resolve(videoRequest.getTmax());
bidRequestBuilder.tmax(videoTmax);
final long timeout = timeoutResolver.resolve(videoRequest.getTmax());
bidRequestBuilder.tmax(timeout);

addRequiredOpenRtbFields(bidRequestBuilder);

Expand All @@ -373,48 +377,50 @@ private void addRequiredOpenRtbFields(BidRequest.BidRequestBuilder bidRequestBui
}

private ExtRequest createExtRequest(BidRequestVideo videoRequest) {
final ExtIncludeBrandCategory extIncludeBrandCategory;
final IncludeBrandCategory includebrandcategory = videoRequest.getIncludebrandcategory();
if (includebrandcategory != null) {
extIncludeBrandCategory = ExtIncludeBrandCategory.of(
includebrandcategory.getPrimaryAdserver(),
includebrandcategory.getPublisher(),
true,
includebrandcategory.getTranslateCategories());
} else {
extIncludeBrandCategory = ExtIncludeBrandCategory.of(null, null, false, null);
}
final ExtRequestPrebidCache cache = ExtRequestPrebidCache.of(null,
ExtRequestPrebidCacheVastxml.of(null, null), null);

List<Integer> durationRangeSec = null;
if (BooleanUtils.isFalse(videoRequest.getPodconfig().getRequireExactDuration())) {
durationRangeSec = videoRequest.getPodconfig().getDurationRangeSec();
}
final ExtIncludeBrandCategory extIncludeBrandCategory = createExtIncludeBrandCategory(videoRequest);

final Podconfig podconfig = videoRequest.getPodconfig();
final List<Integer> durationRangeSec = BooleanUtils.isFalse(podconfig.getRequireExactDuration())
? podconfig.getDurationRangeSec()
: null;

final PriceGranularity priceGranularity = videoRequest.getPricegranularity();
final Integer precision = priceGranularity != null
? priceGranularity.getPrecision()
: null;

PriceGranularity updatedPriceGranularity = precision != null && precision != 0
? priceGranularity
: PriceGranularity.createFromString("med");
? priceGranularity.getPrecision()
: null;
final PriceGranularity updatedPriceGranularity = precision != null && precision != 0
? priceGranularity
: PriceGranularity.createFromString("med");

final ExtRequestTargeting targeting = ExtRequestTargeting.builder()
.pricegranularity(mapper.mapper().valueToTree(updatedPriceGranularity))
.includebidderkeys(true)
.includebrandcategory(extIncludeBrandCategory)
.durationrangesec(durationRangeSec)
.pricegranularity(mapper.mapper().valueToTree(updatedPriceGranularity))
.appendbiddernames(videoRequest.getAppendbiddernames())
.build();

final ExtRequestPrebidCache extReqPrebidCache = ExtRequestPrebidCache.of(null,
ExtRequestPrebidCacheVastxml.of(null, null), null);

final ExtRequestPrebid extRequestPrebid = ExtRequestPrebid.builder()
.cache(extReqPrebidCache)
.cache(cache)
.targeting(targeting)
.build();

return ExtRequest.of(extRequestPrebid);
}

private static ExtIncludeBrandCategory createExtIncludeBrandCategory(BidRequestVideo videoRequest) {
final IncludeBrandCategory includeBrandCategory = videoRequest.getIncludebrandcategory();
if (includeBrandCategory != null) {
return ExtIncludeBrandCategory.of(
includeBrandCategory.getPrimaryAdserver(),
includeBrandCategory.getPublisher(),
true,
includeBrandCategory.getTranslateCategories());
}

return ExtIncludeBrandCategory.of(null, null, false, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.iab.openrtb.response.Bid;
import lombok.Value;

import java.util.Collections;
import java.util.List;
import java.util.Map;

Expand All @@ -17,6 +18,14 @@ public class CategoryMappingResult {

List<String> errors;

public static CategoryMappingResult of(List<BidderResponse> bidderResponses) {
return CategoryMappingResult.of(
Collections.emptyMap(),
Collections.emptyMap(),
bidderResponses,
Collections.emptyList());
}

public String getCategory(Bid bid) {
return biddersToBidsCategories.get(bid);
}
Expand Down
Loading