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 be always executed or not when they're in the execution plan; if the module is not specified it is executed by default
- `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
32 changes: 11 additions & 21 deletions src/main/java/org/prebid/server/hooks/execution/GroupExecutor.java
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved
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.get(hookId.getModuleCode())) {
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 All @@ -66,6 +70,7 @@ public class HookStageExecutor {

private final ExecutionPlan hostExecutionPlan;
private final ExecutionPlan defaultAccountExecutionPlan;
private final Map<String, Boolean> hostModuleExecution;
private final HookCatalog hookCatalog;
private final TimeoutFactory timeoutFactory;
private final Vertx vertx;
Expand All @@ -74,6 +79,7 @@ public class HookStageExecutor {

private HookStageExecutor(ExecutionPlan hostExecutionPlan,
ExecutionPlan defaultAccountExecutionPlan,
Map<String, Boolean> hostModuleExecution,
HookCatalog hookCatalog,
TimeoutFactory timeoutFactory,
Vertx vertx,
Expand All @@ -87,10 +93,12 @@ private HookStageExecutor(ExecutionPlan hostExecutionPlan,
this.vertx = vertx;
this.clock = clock;
this.isConfigToInvokeRequired = isConfigToInvokeRequired;
this.hostModuleExecution = hostModuleExecution;
}

public static HookStageExecutor create(String hostExecutionPlan,
String defaultAccountExecutionPlan,
Map<String, Boolean> hostModuleExecution,
HookCatalog hookCatalog,
TimeoutFactory timeoutFactory,
Vertx vertx,
Expand All @@ -104,6 +112,7 @@ public static HookStageExecutor create(String hostExecutionPlan,
Objects.requireNonNull(mapper),
Objects.requireNonNull(hookCatalog)),
parseAndValidateExecutionPlan(defaultAccountExecutionPlan, mapper, hookCatalog),
hostModuleExecution,
hookCatalog,
Objects.requireNonNull(timeoutFactory),
Objects.requireNonNull(vertx),
Expand All @@ -123,6 +132,7 @@ public Future<HookStageExecutionResult<EntrypointPayload>> executeEntrypointStag
.withExecutionPlan(planForEntrypointStage(endpoint))
.withInitialPayload(EntrypointPayloadImpl.of(queryParams, headers, body))
.withInvocationContextProvider(invocationContextProvider(endpoint))
.withModulesExecution(DefaultedMap.defaultedMap(hostModuleExecution, true))
.withRejectAllowed(true)
.execute();
}
Expand Down Expand Up @@ -259,7 +269,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 +283,31 @@ 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)
.orElseGet(Collections::emptyMap);
AntoxaAntoxic marked this conversation as resolved.
Show resolved Hide resolved

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));
}

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

private static ExecutionPlan parseAndValidateExecutionPlan(
String executionPlan,
JacksonMapper mapper,
Expand Down Expand Up @@ -402,8 +434,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 @@ -8,6 +8,7 @@
import org.prebid.server.hooks.execution.HookStageExecutor;
import org.prebid.server.hooks.v1.Module;
import org.prebid.server.json.JacksonMapper;
import org.prebid.server.settings.model.HooksAdminConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
Expand All @@ -16,6 +17,8 @@

import java.time.Clock;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

@Configuration
public class HooksConfiguration {
Expand All @@ -38,6 +41,9 @@ HookStageExecutor hookStageExecutor(HooksConfigurationProperties hooksConfigurat
return HookStageExecutor.create(
hooksConfiguration.getHostExecutionPlan(),
hooksConfiguration.getDefaultAccountExecutionPlan(),
Optional.ofNullable(hooksConfiguration.getAdmin())
.map(HooksAdminConfig::getModuleExecution)
.orElseGet(Collections::emptyMap),
hookCatalog,
timeoutFactory,
vertx,
Expand All @@ -60,5 +66,7 @@ private static class HooksConfigurationProperties {
String hostExecutionPlan;

String defaultAccountExecutionPlan;

HooksAdminConfig admin;
}
}
Loading
Loading