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 module-execution config on the host level #3594

Merged
merged 2 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 4 additions & 3 deletions docs/config-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,6 @@ 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 Expand Up @@ -443,6 +440,10 @@ If not defined in config all other Health Checkers would be disabled and endpoin
- `analytics.pubstack.buffers.count` - threshold in events count for buffer to send events
- `analytics.pubstack.buffers.report-ttl-ms` - max period between two reports.

## Modules
- `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.modules.require-config-to-invoke` - when enabled it requires a runtime config to exist for a module.

## Debugging
- `debug.override-token` - special string token for overriding Prebid Server account and/or adapter debug information presence in the auction response.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public Future<GroupResult<PAYLOAD>> execute() {
Future<GroupResult<PAYLOAD>> groupFuture = Future.succeededFuture(initialGroupResult);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,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 @@ -90,6 +91,7 @@ public class HookStageExecutor {

private HookStageExecutor(ExecutionPlan hostExecutionPlan,
ExecutionPlan defaultAccountExecutionPlan,
Map<String, Boolean> hostModuleExecution,
HookCatalog hookCatalog,
TimeoutFactory timeoutFactory,
Vertx vertx,
Expand All @@ -105,10 +107,12 @@ private HookStageExecutor(ExecutionPlan hostExecutionPlan,
this.clock = clock;
this.mapper = mapper;
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 @@ -122,6 +126,7 @@ public static HookStageExecutor create(String hostExecutionPlan,
return new HookStageExecutor(
parseAndValidateExecutionPlan(hostExecutionPlan, mapper, hookCatalog),
parseAndValidateExecutionPlan(defaultAccountExecutionPlan, mapper, hookCatalog),
hostModuleExecution,
hookCatalog,
Objects.requireNonNull(timeoutFactory),
Objects.requireNonNull(vertx),
Expand Down Expand Up @@ -185,7 +190,7 @@ public Future<HookStageExecutionResult<EntrypointPayload>> executeEntrypointStag
.withHookProvider(hookProviderForEntrypointStage(context))
.withInitialPayload(EntrypointPayloadImpl.of(queryParams, headers, body))
.withInvocationContextProvider(invocationContextProvider(endpoint))
.withModulesExecution(Collections.emptyMap())
.withModulesExecution(DefaultedMap.defaultedMap(hostModuleExecution, true))
.withRejectAllowed(true)
.execute();
}
Expand Down Expand Up @@ -374,6 +379,7 @@ private Map<String, Boolean> modulesExecutionForAccount(Account account) {
.forEach(module -> resultModulesExecution.computeIfAbsent(module, key -> true));
}

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

Expand Down
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@

import java.time.Clock;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -411,6 +412,70 @@ public void shouldBypassEntrypointHooksWhenNoPlanForStage(VertxTestContext conte
}));
}

@Test
public void shouldBypassEntrypointHooksThatAreDisabled(VertxTestContext context) {
// given
givenEntrypointHook(
"module-alpha",
"hook-a",
immediateHook(InvocationResultUtils.succeeded(
payload -> EntrypointPayloadImpl.of(
payload.queryParams(), payload.headers(), payload.body() + "-abc"),
"moduleAlphaContext")));

givenEntrypointHook(
"module-alpha",
"hook-b",
delayedHook(InvocationResultUtils.succeeded(payload -> EntrypointPayloadImpl.of(
payload.queryParams(), payload.headers(), payload.body() + "-def")), 40));

givenEntrypointHook(
"module-beta",
"hook-a",
delayedHook(InvocationResultUtils.succeeded(payload -> EntrypointPayloadImpl.of(
payload.queryParams(), payload.headers(), payload.body() + "-ghi")), 80));

givenEntrypointHook(
"module-beta",
"hook-b",
immediateHook(InvocationResultUtils.succeeded(
payload -> EntrypointPayloadImpl.of(
payload.queryParams(), payload.headers(), payload.body() + "-jkl"),
"moduleBetaContext")));

final HookStageExecutor executor = HookStageExecutor.create(
executionPlan(singletonMap(
Endpoint.openrtb2_auction,
EndpointExecutionPlan.of(singletonMap(Stage.entrypoint, execPlanTwoGroupsTwoHooksEach())))),
null,
Map.of("module-alpha", false),
hookCatalog,
timeoutFactory,
vertx,
clock,
jacksonMapper,
false);

final HookExecutionContext hookExecutionContext = HookExecutionContext.of(Endpoint.openrtb2_auction);

// when
final Future<HookStageExecutionResult<EntrypointPayload>> future = executor.executeEntrypointStage(
CaseInsensitiveMultiMap.empty(),
CaseInsensitiveMultiMap.empty(),
"body",
hookExecutionContext);

// then
future.onComplete(context.succeeding(result -> {
assertThat(result).isNotNull();
assertThat(result.isShouldReject()).isFalse();
assertThat(result.getPayload()).isNotNull().satisfies(payload ->
assertThat(payload.body()).isEqualTo("body-ghi-jkl"));

context.completeNow();
}));
}

@Test
public void shouldExecuteEntrypointHooksToleratingMisbehavingHooks(VertxTestContext context) {
// given
Expand Down Expand Up @@ -1341,12 +1406,14 @@ public void shouldNotExecuteRawAuctionRequestHooksWhenAccountConfigIsNotRequired
200L,
asList(
HookId.of("module-alpha", "hook-a"),
HookId.of("module-beta", "hook-a"))),
HookId.of("module-beta", "hook-a"),
HookId.of("module-epsilon", "hook-a"))),
ExecutionGroup.of(
200L,
asList(
HookId.of("module-gamma", "hook-b"),
HookId.of("module-delta", "hook-b")))));
HookId.of("module-delta", "hook-b"),
HookId.of("module-zeta", "hook-b")))));

final String hostExecutionPlan = executionPlan(singletonMap(
Endpoint.openrtb2_auction,
Expand All @@ -1355,6 +1422,7 @@ public void shouldNotExecuteRawAuctionRequestHooksWhenAccountConfigIsNotRequired
final HookStageExecutor executor = HookStageExecutor.create(
hostExecutionPlan,
null,
Map.of("module-epsilon", true, "module-zeta", false),
hookCatalog,
timeoutFactory,
vertx,
Expand All @@ -1375,11 +1443,13 @@ public void shouldNotExecuteRawAuctionRequestHooksWhenAccountConfigIsNotRequired
null,
Map.of("module-alpha", mapper.createObjectNode(),
"module-beta", mapper.createObjectNode(),
"module-gamma", mapper.createObjectNode()),
"module-gamma", mapper.createObjectNode(),
"module-zeta", mapper.createObjectNode()),
HooksAdminConfig.builder()
.moduleExecution(Map.of(
"module-alpha", true,
"module-beta", false))
"module-beta", false,
"module-epsilon", false))
.build()))
.build())
.hookExecutionContext(hookExecutionContext)
Expand All @@ -1394,6 +1464,7 @@ public void shouldNotExecuteRawAuctionRequestHooksWhenAccountConfigIsNotRequired
.at(1)
.id("id")
.tmax(1000L)
.site(Site.builder().build())
.build()));

assertThat(hookExecutionContext.getStageOutcomes())
Expand Down Expand Up @@ -1468,6 +1539,7 @@ public void shouldExecuteRawAuctionRequestHooksWhenAccountConfigIsRequired(Vertx
final HookStageExecutor executor = HookStageExecutor.create(
hostExecutionPlan,
null,
Map.of("module-epsilon", true, "module-zeta", false),
hookCatalog,
timeoutFactory,
vertx,
Expand All @@ -1488,11 +1560,13 @@ public void shouldExecuteRawAuctionRequestHooksWhenAccountConfigIsRequired(Vertx
null,
Map.of("module-alpha", mapper.createObjectNode(),
"module-beta", mapper.createObjectNode(),
"module-gamma", mapper.createObjectNode()),
"module-gamma", mapper.createObjectNode(),
"module-zeta", mapper.createObjectNode()),
HooksAdminConfig.builder()
.moduleExecution(Map.of(
"module-alpha", true,
"module-beta", false))
"module-beta", false,
"module-epsilon", false))
.build()))
.build())
.hookExecutionContext(hookExecutionContext)
Expand All @@ -1506,6 +1580,7 @@ public void shouldExecuteRawAuctionRequestHooksWhenAccountConfigIsRequired(Vertx
assertThat(payload.bidRequest()).isEqualTo(BidRequest.builder()
.at(1)
.id("id")
.site(Site.builder().build())
.build()));

assertThat(hookExecutionContext.getStageOutcomes())
Expand Down Expand Up @@ -3298,6 +3373,7 @@ private HookStageExecutor createExecutor(String hostExecutionPlan, String defaul
return HookStageExecutor.create(
hostExecutionPlan,
defaultAccountExecutionPlan,
Collections.emptyMap(),
hookCatalog,
timeoutFactory,
vertx,
Expand Down
Loading