Skip to content

optable-targeting: Review follow-ups (stored-request leak, plan resolution, api-timeout) - #6

Open
justadreamer wants to merge 14 commits into
optable-targeting-featuresfrom
fix/optable-targeting-review-followups
Open

justadreamer wants to merge 14 commits into
optable-targeting-featuresfrom
fix/optable-targeting-review-followups

Conversation

@justadreamer

@justadreamer justadreamer commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up fixes for the optable-targeting review. Merges cleanly into optable-targeting-features.

Why / what changed

  • The auction request kept user.ext.optable when the raw hook deferred the call. The bidder-request hook now cleans bidder requests, but analytics adapters and the debug output still saw the IDs unless the processed hook was in the plan. The raw hook now always cleans and keeps user.ext.optable in the module context for the deferred call.
  • Mixed inline and stored imps. The raw hook now defers whenever the request or any imp references a stored request, so bidders from stored imps are sampled too.
  • Hook exceptions skipped the auction-level cleaner. The raw and processed hooks catch the exception and still clean the request.
  • CompositeHookExecutionPlan:
    • It now checks the host plan plus the account plan, falling back to the default account plan, for the request's endpoint, with no cache.
    • The call awaited by the bidder-request hook is limited by a new api-timeout parameter, or by the remaining auction time when it is not set, instead of the first group's timeout.
  • The legacy processed-only setup now respects enrich-web/enrich-app and sampling.
  • BidRequestCleanerTest didn't compile after the cleaner was split into auction and bidder variants. It now tests the bidder variant.
  • README: documents api-timeout and legacy-mode sampling.

AMP and video are left as before: the raw stage doesn't run for them, so they aren't enriched.

Testing

  • Module tests pass.
  • OptableStoredRequestFlowTest runs a request through the raw, processed and bidder-request hooks, covering:
    • stored imps
    • app that comes from a stored request
    • mixed inline and stored imps
    • cleaning at the raw stage
    • sampling that runs only once

An account can have the module hooks in its execution plan without a
module config of its own. ConfigResolver passed the null config to the
JSON merger, which threw and failed every hook of the module.
The fallback looked for imp.ext.bidder, which is not a format the core
knows. Old-style params sit directly under imp.ext and the core moves
them to imp.ext.prebid.bidder for every imp that has no bidders there,
so the sampler now applies the same rule per imp instead of falling back
only when no imp at all has imp.ext.prebid.bidder.
An account config with "enrichment-percentage": null or
"bidder-enrichment-percentages": null overrides the defaults of the
properties class, and the sampler then failed on unboxing.
… mixed stored imps

When the raw hook deferred the call to the processed hook it returned
no_action, so user.ext.optable reached every bidder unless the processed
hook was in the plan. The raw hook now always cleans and keeps
user.ext.optable in the module context for the deferred call.

The raw hook also defers whenever the request or any imp references a
stored request, since bidders from stored imps were otherwise never
sampled. Sampling now runs only once, at the stage that makes the call.

The README now lists the processed hook as required.
An exception in the raw or processed auction request hook failed the hook
without applying the cleaner, so user.ext.optable reached the bidders.
Both hooks now catch it, log it and still return the cleaner update.

The call and the bidders to enrich are set together, so the bidder
request hook never sees bidders without a call to await.
…pi-timeout

CompositeHookExecutionPlan ignored hooks.default-account-execution-plan,
only looked at /openrtb2/auction, took the timeout of the first group of
the bidder request stage and cached the per-account result forever.

It now only tells whether the bidder request hook is configured for the
request, combining the host plan with the account plan (or the default
account plan) for the request's endpoint, without caching. Whether the
raw hook has run comes from the module context.

The call awaited by the bidder request hook is bound by the new
api-timeout parameter, or by the time remaining for the auction.

The raw stage never runs for amp and video requests, so when the bidder
request hook is configured the processed hook now starts the call there
instead of passing through without one. When the raw hook has run and the
bidder request hook is absent, the processed hook awaits the early call
and enriches the request, as before.
…gacy setup

Without the raw and bidder request hooks the processed hook called the
API and enriched every request, whatever enrich-web, enrich-app and the
enrichment percentages said. It now skips disabled traffic sources and
only calls the API when sampling selects at least one bidder.
… fix/optable-targeting-review-followups

# Conflicts:
#	extra/modules/optable-targeting/README.md
#	extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/BidderEnrichmentSampler.java
… fix/optable-targeting-review-followups

# Conflicts:
#	extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/OptableTargetingFlowResolver.java
The raw auction request stage does not run for them, and they were not
enriched before, so the processed hook keeps passing them through when
the bidder request hook is configured instead of starting the call.
… fix/optable-targeting-review-followups

Kept this branch's flow resolver and execution plan: it already samples once, defers stored imps and reads the default account plan. Adapted OptableTargetingFlowResolverTest to the raw-stage API here, where the cleaner is applied whether or not the call is deferred.
…ion or bidder request

Walks a request carrying every user.ext.optable id through each hook setup (raw + processed + bidder, processed + bidder, processed only), request shape (inline site/app, stored imp, app from a stored request, disabled traffic source) and outcome (enriched, sampled out, no data, API error, hook exception). Each stage works on a copy, as the core's stored request merge and bidder request split do, so a cleaner applied later cannot hide a leak earlier.
… fix/optable-targeting-review-followups

# Conflicts:
#	extra/modules/optable-targeting/src/main/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/OptableTargetingFlowResolver.java
#	extra/modules/optable-targeting/src/test/java/org/prebid/server/hooks/modules/optable/targeting/v1/core/OptableTargetingFlowResolverTest.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant