Skip to content

v6.2: patch decomposition into atomic verbs for update_media_buy #1071

Description

@bokelley

Status

Deferred from 6.1. Tracking the SalesPlatform polish layer that simplifies updateMediaBuy for adopters.

Today's shape (6.0 / 6.1)

updateMediaBuy(buyId, patch: UpdateMediaBuyRequest, ctx): Promise<UpdateMediaBuySuccess>

Adopter receives the whole wire patch and figures out what changed: which packages were added, which removed, which had targeting overrides changed, whether `active` flipped, etc. Every adopter writes the same diff/dispatch boilerplate.

Proposed 6.2 shape

The SDK pre-reads current state via a required `getMediaBuy(buyId)` primitive, computes the diff against the wire patch, and decomposes into atomic verbs the adopter implements:

// Required new primitive (single-id read):
getMediaBuy(buyId: string, ctx): Promise<NativeMediaBuy>;

// Atomic verbs (replaces the omnibus updateMediaBuy):
addPackage(buyId, productRef, package, ctx): Promise<NativePackage>;
removePackage(buyId, packageId, ctx): Promise<void>;
updatePackage(buyId, packageId, patch, ctx): Promise<NativePackage>;
addCreativeToPackage(buyId, packageId, creative, ctx): Promise<void>;
removeCreativeFromPackage(buyId, packageId, creativeId, ctx): Promise<void>;
pauseMediaBuy(buyId, ctx): Promise<void>;
resumeMediaBuy(buyId, ctx): Promise<void>;
archiveMediaBuy(buyId, ctx): Promise<void>;

SDK does:

  1. Pre-read `getMediaBuy(buyId)` for current state
  2. Validate `package_id`s in the patch against current state → throw `PACKAGE_NOT_FOUND` before any platform writes
  3. Diff patch against current state → decompose into atomic-verb sequence
  4. Call adopter verbs in sequence
  5. Post-read `getMediaBuy(buyId)` → project to wire response via StatusMappers

Why this is 6.2 not 6.1

  • Requires new `getMediaBuy(id)` primitive — currently optional, becomes required
  • Patch-decomposition logic is non-trivial (creative_assignments override-vs-add/remove, targeting_overlay merge semantics, package pricing changes)
  • Some platforms have native atomic patches (GAM `lineItem.update`) — needs an opt-out escape hatch where adopter overrides the decomposed shape
  • Pre-mutation read adds a round-trip on every update — perf model needs documentation
  • Worth validating against Scope3, Prebid, AudioStack adapter implementations before locking

What 6.1 ships instead

`ctx_metadata` round-trip cache (this PR) covers the storage primitive needed for the auto-everything redesign. Adopters can already use `ctx.ctxMetadata.set('package', id, ...)` on `createMediaBuy` to stash per-package state, and the patch decomposition can read it later without an extra DB hop. So 6.2 is purely the request-shape simplification — the storage substrate is there.

Linked

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions