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

Module Execution Host Config Check #3566

Merged
merged 12 commits into from
Dec 4, 2024
1 change: 1 addition & 0 deletions docs/application-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Keep in mind following restrictions:
- `cookie-sync.pri` - a list of prioritized bidder codes
- `cookie-sync.coop-sync.default` - if the "coopSync" value isn't specified in the `/cookie_sync` request, use this
- `hooks` - configuration for Prebid Server Modules. For further details, see: https://docs.prebid.org/prebid-server/pbs-modules/index.html#2-define-an-execution-plan
- `hooks.admin.module-execution` - a key-value map, where a key is a module name and a value is a boolean, that defines whether modules hooks should/should not be always executed; if the module is not specified it is executed by default when it's present in the execution plan
- `settings.geo-lookup` - enables geo lookup for account if true. Defaults to false.

Here are the definitions of the "purposes" that can be defined in the GDPR setting configurations:
Expand Down
3 changes: 3 additions & 0 deletions docs/config-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@ contain 'WHERE last_updated > ?' for MySQL and 'WHERE last_updated > $1' for Pos
For targeting available next options:
- `settings.targeting.truncate-attr-chars` - set the max length for names of targeting keywords (0 means no truncation).

For modules:
- `settings.modules.require-config-to-invoke` - when enabled it requires a runtime config to exist for a module.

## Host Cookie
- `host-cookie.optout-cookie.name` - set the cookie name for optout checking.
- `host-cookie.optout-cookie.value` - set the cookie value for optout checking.
Expand Down
32 changes: 11 additions & 21 deletions src/main/java/org/prebid/server/hooks/execution/GroupExecutor.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.prebid.server.hooks.execution;

import com.fasterxml.jackson.databind.node.ObjectNode;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Promise;
Expand All @@ -9,16 +8,13 @@
import org.prebid.server.hooks.execution.model.HookExecutionContext;
import org.prebid.server.hooks.execution.model.HookId;
import org.prebid.server.hooks.v1.Hook;
import org.prebid.server.hooks.v1.InvocationAction;
import org.prebid.server.hooks.v1.InvocationContext;
import org.prebid.server.hooks.v1.InvocationResult;
import org.prebid.server.hooks.v1.InvocationResultImpl;
import org.prebid.server.hooks.v1.InvocationStatus;
import org.prebid.server.hooks.v1.auction.AuctionInvocationContext;
import org.prebid.server.log.ConditionalLogger;
import org.prebid.server.log.LoggerFactory;

import java.time.Clock;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Supplier;
Expand All @@ -30,7 +26,7 @@ class GroupExecutor<PAYLOAD, CONTEXT extends InvocationContext> {

private final Vertx vertx;
private final Clock clock;
private final boolean isConfigToInvokeRequired;
private final Map<String, Boolean> modulesExecution;

private ExecutionGroup group;
private PAYLOAD initialPayload;
Expand All @@ -39,18 +35,19 @@ class GroupExecutor<PAYLOAD, CONTEXT extends InvocationContext> {
private HookExecutionContext hookExecutionContext;
private boolean rejectAllowed;

private GroupExecutor(Vertx vertx, Clock clock, boolean isConfigToInvokeRequired) {
private GroupExecutor(Vertx vertx, Clock clock, Map<String, Boolean> modulesExecution) {

this.vertx = vertx;
this.clock = clock;
this.isConfigToInvokeRequired = isConfigToInvokeRequired;
this.modulesExecution = modulesExecution;
}

public static <PAYLOAD, CONTEXT extends InvocationContext> GroupExecutor<PAYLOAD, CONTEXT> create(
Vertx vertx,
Clock clock,
boolean isConfigToInvokeRequired) {
Map<String, Boolean> modulesExecution) {

return new GroupExecutor<>(vertx, clock, isConfigToInvokeRequired);
return new GroupExecutor<>(vertx, clock, modulesExecution);
}

public GroupExecutor<PAYLOAD, CONTEXT> withGroup(ExecutionGroup group) {
Expand Down Expand Up @@ -90,6 +87,10 @@ public Future<GroupResult<PAYLOAD>> execute() {
Future<GroupResult<PAYLOAD>> groupFuture = Future.succeededFuture(initialGroupResult);

for (final HookId hookId : group.getHookSequence()) {
if (!modulesExecution.getOrDefault(hookId.getModuleCode(), true)) {
continue;
}

final Hook<PAYLOAD, CONTEXT> hook = hookProvider.apply(hookId);

final long startTime = clock.millis();
Expand All @@ -116,17 +117,6 @@ private Future<InvocationResult<PAYLOAD>> executeHook(
}

final CONTEXT invocationContext = invocationContextProvider.apply(timeout, hookId, moduleContextFor(hookId));

if (isConfigToInvokeRequired && invocationContext instanceof AuctionInvocationContext) {
final ObjectNode accountConfig = ((AuctionInvocationContext) invocationContext).accountConfig();
if (accountConfig == null || accountConfig.isNull()) {
return Future.succeededFuture(InvocationResultImpl.<PAYLOAD>builder()
.status(InvocationStatus.success)
.action(InvocationAction.no_invocation)
.build());
}
}

return executeWithTimeout(() -> hook.call(groupResult.payload(), invocationContext), timeout);
}

Expand Down
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.iab.openrtb.response.BidResponse;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import org.apache.commons.collections4.map.DefaultedMap;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.auction.model.AuctionContext;
Expand Down Expand Up @@ -46,14 +47,17 @@
import org.prebid.server.model.CaseInsensitiveMultiMap;
import org.prebid.server.model.Endpoint;
import org.prebid.server.settings.model.Account;
import org.prebid.server.settings.model.HooksAdminConfig;
import org.prebid.server.settings.model.AccountHooksConfiguration;

import java.time.Clock;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

public class HookStageExecutor {
Expand Down Expand Up @@ -123,6 +127,7 @@ public Future<HookStageExecutionResult<EntrypointPayload>> executeEntrypointStag
.withExecutionPlan(planForEntrypointStage(endpoint))
.withInitialPayload(EntrypointPayloadImpl.of(queryParams, headers, body))
.withInvocationContextProvider(invocationContextProvider(endpoint))
.withModulesExecution(Collections.emptyMap())
.withRejectAllowed(true)
.execute();
}
Expand Down Expand Up @@ -259,7 +264,7 @@ private <PAYLOAD, CONTEXT extends InvocationContext> StageExecutor<PAYLOAD, CONT
String entity,
HookExecutionContext context) {

return StageExecutor.<PAYLOAD, CONTEXT>create(hookCatalog, vertx, clock, isConfigToInvokeRequired)
return StageExecutor.<PAYLOAD, CONTEXT>create(hookCatalog, vertx, clock)
.withStage(stage)
.withEntity(entity)
.withHookExecutionContext(context);
Expand All @@ -273,9 +278,30 @@ private <PAYLOAD, CONTEXT extends InvocationContext> StageExecutor<PAYLOAD, CONT
Endpoint endpoint) {

return stageExecutor(stage, entity, context)
.withModulesExecution(modulesExecutionForAccount(account))
.withExecutionPlan(planForStage(account, endpoint, stage.stage()));
}

private Map<String, Boolean> modulesExecutionForAccount(Account account) {
final Map<String, Boolean> accountModulesExecution = Optional.ofNullable(account.getHooks())
.map(AccountHooksConfiguration::getAdmin)
.map(HooksAdminConfig::getModuleExecution)
.orElse(Collections.emptyMap());

final Map<String, Boolean> resultModulesExecution = new HashMap<>(accountModulesExecution);

if (isConfigToInvokeRequired) {
Optional.ofNullable(account.getHooks())
.map(AccountHooksConfiguration::getModules)
.map(Map::keySet)
.stream()
.flatMap(Collection::stream)
.forEach(module -> resultModulesExecution.computeIfAbsent(module, key -> true));
}

return DefaultedMap.defaultedMap(resultModulesExecution, !isConfigToInvokeRequired);
}

private static ExecutionPlan parseAndValidateExecutionPlan(
String executionPlan,
JacksonMapper mapper,
Expand Down Expand Up @@ -402,8 +428,7 @@ private InvocationContextProvider<BidderInvocationContext> bidderInvocationConte
String bidder) {

return (timeout, hookId, moduleContext) -> BidderInvocationContextImpl.of(
auctionInvocationContext(endpoint, timeout, auctionContext, hookId, moduleContext),
bidder);
auctionInvocationContext(endpoint, timeout, auctionContext, hookId, moduleContext), bidder);
}

private Timeout createTimeout(Long timeout) {
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/org/prebid/server/hooks/execution/StageExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@

import java.time.Clock;
import java.util.ArrayList;
import java.util.Map;

class StageExecutor<PAYLOAD, CONTEXT extends InvocationContext> {

private final HookCatalog hookCatalog;
private final Vertx vertx;
private final Clock clock;
private final boolean isConfigToInvokeRequired;

private StageWithHookType<? extends Hook<PAYLOAD, CONTEXT>> stage;
private String entity;
Expand All @@ -27,21 +27,20 @@ class StageExecutor<PAYLOAD, CONTEXT extends InvocationContext> {
private InvocationContextProvider<CONTEXT> invocationContextProvider;
private HookExecutionContext hookExecutionContext;
private boolean rejectAllowed;
private Map<String, Boolean> modulesExecution;

private StageExecutor(HookCatalog hookCatalog, Vertx vertx, Clock clock, boolean isConfigToInvokeRequired) {
private StageExecutor(HookCatalog hookCatalog, Vertx vertx, Clock clock) {
this.hookCatalog = hookCatalog;
this.vertx = vertx;
this.clock = clock;
this.isConfigToInvokeRequired = isConfigToInvokeRequired;
}

public static <PAYLOAD, CONTEXT extends InvocationContext> StageExecutor<PAYLOAD, CONTEXT> create(
HookCatalog hookCatalog,
Vertx vertx,
Clock clock,
boolean isConfigToInvokeRequired) {
Clock clock) {

return new StageExecutor<>(hookCatalog, vertx, clock, isConfigToInvokeRequired);
return new StageExecutor<>(hookCatalog, vertx, clock);
}

public StageExecutor<PAYLOAD, CONTEXT> withStage(StageWithHookType<? extends Hook<PAYLOAD, CONTEXT>> stage) {
Expand Down Expand Up @@ -81,6 +80,11 @@ public StageExecutor<PAYLOAD, CONTEXT> withRejectAllowed(boolean rejectAllowed)
return this;
}

public StageExecutor<PAYLOAD, CONTEXT> withModulesExecution(Map<String, Boolean> modulesExecution) {
this.modulesExecution = modulesExecution;
return this;
}

public Future<HookStageExecutionResult<PAYLOAD>> execute() {
Future<StageResult<PAYLOAD>> stageFuture = Future.succeededFuture(StageResult.of(initialPayload, entity));

Expand All @@ -97,7 +101,7 @@ public Future<HookStageExecutionResult<PAYLOAD>> execute() {
}

private Future<GroupResult<PAYLOAD>> executeGroup(ExecutionGroup group, PAYLOAD initialPayload) {
return GroupExecutor.<PAYLOAD, CONTEXT>create(vertx, clock, isConfigToInvokeRequired)
return GroupExecutor.<PAYLOAD, CONTEXT>create(vertx, clock, modulesExecution)
.withGroup(group)
.withInitialPayload(initialPayload)
.withHookProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ public class AccountHooksConfiguration {
ExecutionPlan executionPlan;

Map<String, ObjectNode> modules;

HooksAdminConfig admin;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.prebid.server.settings.model;

import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Builder;
import lombok.Value;

import java.util.Map;

@Builder
@Value
public class HooksAdminConfig {

@JsonAlias("module-execution")
Map<String, Boolean> moduleExecution;

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ class AccountHooksConfiguration {
@JsonProperty("execution_plan")
ExecutionPlan executionPlanSnakeCase
PbsModulesConfig modules
AdminConfig admin
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.prebid.server.functional.model.config

import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.fasterxml.jackson.databind.annotation.JsonNaming
import groovy.transform.ToString
import org.prebid.server.functional.model.ModuleName

@ToString(includeNames = true, ignoreNulls = true)
@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy)
class AdminConfig {

Map<ModuleName, Boolean> moduleExecution
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package org.prebid.server.functional.model.response.auction
import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.fasterxml.jackson.databind.annotation.JsonNaming
import groovy.transform.ToString
import org.prebid.server.functional.model.config.Stage

@ToString(includeNames = true, ignoreNulls = true)
@JsonNaming(PropertyNamingStrategies.LowerCaseStrategy)
class TraceOutcome {

Stage entity
String entity
Long executionTimeMillis
List<TraceGroup> groups
}
Loading
Loading