Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,24 @@ public GreenbidsInvocationResult createGreenbidsInvocationResult(
final String greenbidsId = UUID.randomUUID().toString();
final boolean isExploration = isExploration(greenbidsConfig, greenbidsId);

final BidRequest updatedBidRequest = isExploration
final List<Imp> updatedImps = updateImps(bidRequest, impsBiddersFilterMap);

final BidRequest updatedBidRequest = isExploration || updatedImps.isEmpty()
? bidRequest
: bidRequest.toBuilder()
.imp(updateImps(bidRequest, impsBiddersFilterMap))
.imp(updatedImps)
.build();
final InvocationAction invocationAction = isExploration
? InvocationAction.no_action
: InvocationAction.update;
final Map<String, Map<String, Boolean>> impsBiddersFilterMapToAnalyticsTag = isExploration
? keepAllBiddersForAnalyticsResult(impsBiddersFilterMap)
: impsBiddersFilterMap;

final InvocationAction invocationAction = updatedImps.isEmpty()
? InvocationAction.reject
: isExploration
? InvocationAction.no_action
: InvocationAction.update;

final Map<String, Ortb2ImpExtResult> ort2ImpExtResultMap = createOrtb2ImpExtForImps(
bidRequest, impsBiddersFilterMapToAnalyticsTag, greenbidsId, isExploration);
bidRequest, impsBiddersFilterMap, greenbidsId, isExploration);
final AnalyticsResult analyticsResult = AnalyticsResult.of(
"success", ort2ImpExtResultMap, null, null);
"success", ort2ImpExtResultMap);

return GreenbidsInvocationResult.of(updatedBidRequest, invocationAction, analyticsResult);
}
Expand All @@ -61,10 +64,15 @@ private Boolean isExploration(GreenbidsConfig greenbidsConfig, String greenbidsI

private List<Imp> updateImps(BidRequest bidRequest, Map<String, Map<String, Boolean>> impsBiddersFilterMap) {
return bidRequest.getImp().stream()
.filter(imp -> isImpKept(imp, impsBiddersFilterMap))
.map(imp -> updateImp(imp, impsBiddersFilterMap.get(imp.getId())))
.toList();
}

private boolean isImpKept(Imp imp, Map<String, Map<String, Boolean>> impsBiddersFilterMap) {
return impsBiddersFilterMap.get(imp.getId()).values().stream().anyMatch(isKept -> isKept);
Comment on lines +72 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that it is time for us to change the structure from Map<String, Map<String, Boolean>> to Map<String, Set<String>> impIdToKeptBidders (from the moment of creation in the processProbabilities method).

This is only a suggestion, it is not necessary to change it now.

}

private Imp updateImp(Imp imp, Map<String, Boolean> bidderFilterMap) {
return imp.toBuilder()
.ext(updateImpExt(imp.getExt(), bidderFilterMap))
Expand All @@ -83,16 +91,6 @@ private ObjectNode updateImpExt(ObjectNode impExt, Map<String, Boolean> bidderFi
return updatedExt;
}

private Map<String, Map<String, Boolean>> keepAllBiddersForAnalyticsResult(
Map<String, Map<String, Boolean>> impsBiddersFilterMap) {

return impsBiddersFilterMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> true))));
}

private Map<String, Ortb2ImpExtResult> createOrtb2ImpExtForImps(
BidRequest bidRequest,
Map<String, Map<String, Boolean>> impsBiddersFilterMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,4 @@ public class AnalyticsResult {
String status;

Map<String, Ortb2ImpExtResult> values;

String bidder;

String impId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.iab.openrtb.request.BidRequest;
import io.vertx.core.Future;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.prebid.server.analytics.reporter.greenbids.model.ExplorationResult;
import org.prebid.server.analytics.reporter.greenbids.model.Ortb2ImpExtResult;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.exception.PreBidException;
Expand Down Expand Up @@ -38,6 +40,7 @@
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.AccountHooksConfiguration;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -155,55 +158,63 @@ private InvocationResult<AuctionRequestPayload> toInvocationResult(
AnalyticsResult analyticsResult,
InvocationAction action) {

final List<AnalyticsResult> analyticsResults = analyticsResult != null
? Collections.singletonList(analyticsResult)
: Collections.emptyList();

return switch (action) {
case InvocationAction.update -> InvocationResultImpl
.<AuctionRequestPayload>builder()
.status(InvocationStatus.success)
.action(action)
.payloadUpdate(payload -> AuctionRequestPayloadImpl.of(bidRequest))
.analyticsTags(toAnalyticsTags(analyticsResults))
.analyticsTags(toAnalyticsTags(analyticsResult))
.build();
default -> InvocationResultImpl
.<AuctionRequestPayload>builder()
.status(InvocationStatus.success)
.action(action)
.analyticsTags(toAnalyticsTags(analyticsResults))
.analyticsTags(toAnalyticsTags(analyticsResult))
.build();
};
}

private Tags toAnalyticsTags(List<AnalyticsResult> analyticsResults) {
if (CollectionUtils.isEmpty(analyticsResults)) {
private Tags toAnalyticsTags(AnalyticsResult analyticsResult) {
if (analyticsResult == null) {
return null;
}

return TagsImpl.of(Collections.singletonList(ActivityImpl.of(
ACTIVITY,
SUCCESS_STATUS,
toResults(analyticsResults))));
toResults(analyticsResult))));
}

private List<Result> toResults(List<AnalyticsResult> analyticsResults) {
return analyticsResults.stream()
.map(this::toResult)
private List<Result> toResults(AnalyticsResult analyticsResult) {
return analyticsResult.getValues().entrySet().stream()
.map(entry -> toResult(analyticsResult.getStatus(), entry))
.toList();
}

private Result toResult(AnalyticsResult analyticsResult) {
private Result toResult(String status, Map.Entry<String, Ortb2ImpExtResult> entry) {
final String impId = entry.getKey();
final Ortb2ImpExtResult ortb2ImpExtResult = entry.getValue();
final List<String> removedBidders = Optional.ofNullable(ortb2ImpExtResult)
.map(Ortb2ImpExtResult::getGreenbids)
.map(ExplorationResult::getKeptInAuction)
.map(Map::entrySet)
.stream()
.flatMap(Collection::stream)
.filter(e -> BooleanUtils.isFalse(e.getValue()))
.map(Map.Entry::getKey)
.toList();

return ResultImpl.of(
analyticsResult.getStatus(),
toObjectNode(analyticsResult.getValues()),
status,
toObjectNode(entry),
AppliedToImpl.builder()
.bidders(Collections.singletonList(analyticsResult.getBidder()))
.impIds(Collections.singletonList(analyticsResult.getImpId()))
.impIds(Collections.singletonList(impId))
.bidders(removedBidders.isEmpty() ? null: removedBidders)
.build());
}

private ObjectNode toObjectNode(Map<String, Ortb2ImpExtResult> values) {
private ObjectNode toObjectNode(Map.Entry<String, Ortb2ImpExtResult> values) {
return values != null ? mapper.valueToTree(values) : null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenBidRequest;
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenDevice;
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenImpExt;
import static org.prebid.server.hooks.modules.greenbids.real.time.data.util.TestBidRequestProvider.givenImpExtToFilterAllBidders;

@ExtendWith(MockitoExtension.class)
public class GreenbidsInvocationServiceTest {
Expand Down Expand Up @@ -69,7 +70,6 @@ public void createGreenbidsInvocationResultShouldReturnUpdateBidRequestWhenNotEx
assertThat(keptInAuction.get("rubicon")).isTrue();
assertThat(keptInAuction.get("appnexus")).isFalse();
assertThat(keptInAuction.get("pubmatic")).isFalse();

}

@Test
Expand Down Expand Up @@ -104,8 +104,87 @@ public void createGreenbidsInvocationResultShouldReturnNoActionWhenExploration()
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue();
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
assertThat(keptInAuction.get("rubicon")).isTrue();
assertThat(keptInAuction.get("appnexus")).isTrue();
assertThat(keptInAuction.get("pubmatic")).isTrue();
assertThat(keptInAuction.get("appnexus")).isFalse();
assertThat(keptInAuction.get("pubmatic")).isFalse();
}

@Test
public void createGreenbidsInvocationResultShouldReturnRejectWhenAllImpsFiltered() {
// given
final Banner banner = givenBanner();
final Imp imp = Imp.builder()
.id("adunitcodevalue")
.ext(givenImpExt())
.banner(banner)
.build();
final Device device = givenDevice(identity());
final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp), device);
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = givenFilterMapWithAllFilteredImps();
final GreenbidsConfig greenbidsConfig = givenPartner(1.0);

// when
final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult(
greenbidsConfig, bidRequest, impsBiddersFilterMap);

// then
final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt()
.get("prebid").get("bidder");
final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue");
final Map<String, Boolean> keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction();

assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.reject);
assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue();
assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isTrue();
assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isTrue();
assertThat(ortb2ImpExtResult).isNotNull();
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isTrue();
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
assertThat(keptInAuction.get("rubicon")).isFalse();
assertThat(keptInAuction.get("appnexus")).isFalse();
assertThat(keptInAuction.get("pubmatic")).isFalse();
}

@Test
public void createGreenbidsInvocationResultShouldRemoveImpFromUpdateBidRequestWhenAllBiddersFiltered() {
// given
final Banner banner = givenBanner();
final Imp imp1 = Imp.builder()
.id("adunitcodevalue1")
.ext(givenImpExt())
.banner(banner)
.build();
final Imp imp2 = Imp.builder()
.id("adunitcodevalue2")
.ext(givenImpExtToFilterAllBidders())
.banner(banner)
.build();
final Device device = givenDevice(identity());
final BidRequest bidRequest = givenBidRequest(request -> request, List.of(imp1, imp2), device);
final Map<String, Map<String, Boolean>> impsBiddersFilterMap = givenFilterMapWithAllFilteredBiddersInImp();
final GreenbidsConfig greenbidsConfig = givenPartner(0.0);

// when
final GreenbidsInvocationResult result = target.createGreenbidsInvocationResult(
greenbidsConfig, bidRequest, impsBiddersFilterMap);

// then
final JsonNode updatedBidRequestExtPrebidBidders = result.getUpdatedBidRequest().getImp().getFirst().getExt()
.get("prebid").get("bidder");
final Ortb2ImpExtResult ortb2ImpExtResult = result.getAnalyticsResult().getValues().get("adunitcodevalue1");
final Map<String, Boolean> keptInAuction = ortb2ImpExtResult.getGreenbids().getKeptInAuction();

assertThat(result.getInvocationAction()).isEqualTo(InvocationAction.update);
assertThat(result.getUpdatedBidRequest().getImp()).hasSize(1);
assertThat(updatedBidRequestExtPrebidBidders.has("rubicon")).isTrue();
assertThat(updatedBidRequestExtPrebidBidders.has("appnexus")).isFalse();
assertThat(updatedBidRequestExtPrebidBidders.has("pubmatic")).isFalse();
assertThat(ortb2ImpExtResult).isNotNull();
assertThat(ortb2ImpExtResult.getGreenbids().getIsExploration()).isFalse();
assertThat(ortb2ImpExtResult.getGreenbids().getFingerprint()).isNotNull();
assertThat(keptInAuction.get("rubicon")).isTrue();
assertThat(keptInAuction.get("appnexus")).isFalse();
assertThat(keptInAuction.get("pubmatic")).isFalse();

}

private Map<String, Map<String, Boolean>> givenImpsBiddersFilterMap() {
Expand All @@ -120,6 +199,34 @@ private Map<String, Map<String, Boolean>> givenImpsBiddersFilterMap() {
return impsBiddersFilterMap;
}

private Map<String, Map<String, Boolean>> givenFilterMapWithAllFilteredImps() {
final Map<String, Boolean> biddersFitlerMap = new HashMap<>();
biddersFitlerMap.put("rubicon", false);
biddersFitlerMap.put("appnexus", false);
biddersFitlerMap.put("pubmatic", false);

final Map<String, Map<String, Boolean>> impsBiddersFilterMap = new HashMap<>();
impsBiddersFilterMap.put("adunitcodevalue", biddersFitlerMap);

return impsBiddersFilterMap;
}

private Map<String, Map<String, Boolean>> givenFilterMapWithAllFilteredBiddersInImp() {
final Map<String, Boolean> biddersFitlerMapForKeptImp = new HashMap<>();
biddersFitlerMapForKeptImp.put("rubicon", true);
biddersFitlerMapForKeptImp.put("appnexus", false);
biddersFitlerMapForKeptImp.put("pubmatic", false);

final Map<String, Boolean> biddersFitlerMapForRemovedImp = new HashMap<>();
biddersFitlerMapForRemovedImp.put("appnexus", false);

final Map<String, Map<String, Boolean>> impsBiddersFilterMap = new HashMap<>();
impsBiddersFilterMap.put("adunitcodevalue1", biddersFitlerMapForKeptImp);
impsBiddersFilterMap.put("adunitcodevalue2", biddersFitlerMapForRemovedImp);

return impsBiddersFilterMap;
}

private GreenbidsConfig givenPartner(Double explorationRate) {
return GreenbidsConfig.of("test-pbuid", 0.60, explorationRate);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@ public static ObjectNode givenImpExt() {
return extNode;
}

public static ObjectNode givenImpExtToFilterAllBidders() {
final ObjectNode bidderNode = MAPPER.createObjectNode();

final ObjectNode appnexusNode = MAPPER.createObjectNode();
appnexusNode.put("placementId", 789);
bidderNode.set("appnexus", appnexusNode);

final ObjectNode prebidNode = MAPPER.createObjectNode();
prebidNode.set("bidder", bidderNode);

final ObjectNode extNode = MAPPER.createObjectNode();
extNode.set("prebid", prebidNode);
extNode.set("tid", TextNode.valueOf("af65045c-2774-44c2-a949-4f42d5c9e179"));

return extNode;
}

public static Device givenDevice(UnaryOperator<Device.DeviceBuilder> deviceCustomizer, String countryAlpha3) {
final String userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36"
+ " (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36";
Expand Down
Loading
Loading