Skip to content
This repository has been archived by the owner on Dec 22, 2022. It is now read-only.

Commit

Permalink
Cache vast xml (prebid#643)
Browse files Browse the repository at this point in the history
* Made some changes to support VAST cacheing.

* Implemented vastxml cacheing.

* Fixed JSON in markdown.

* Added endpoint contract tests.

* Removed redundant line.
  • Loading branch information
dbemiller authored Aug 6, 2018
1 parent b664562 commit 78ad79f
Show file tree
Hide file tree
Showing 20 changed files with 458 additions and 202 deletions.
16 changes: 12 additions & 4 deletions docs/endpoints/openrtb2/auction.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,16 @@ Bids can be temporarily cached on the server by sending the following data as `r

```
{
"bids": {}
"bids": {},
"vastxml": {}
}
```

This property has no effect unless `request.ext.prebid.targeting` is also set in the request.
If present, Prebid Server will make a _best effort_ to include these extra `bid.ext.prebid.targeting` keys:
Both `bids` and `vastxml` are optional, but one of the two is required. Thils property will have no effect
unless `request.ext.prebid.targeting` is also set in the request.

If `bids` is present, Prebid Server will make a _best effort_ to include these extra
`bid.ext.prebid.targeting` keys:

- `hb_cache_id`: On the highest overall Bid in each Imp.
- `hb_cache_id_{bidderName}`: On the highest Bid from {bidderName} in each Imp.
Expand All @@ -317,7 +321,11 @@ Clients _should not assume_ that these keys will exist, just because they were r
If they exist, the value will be a UUID which can be used to fetch Bid JSON from [Prebid Cache](https://github.com/prebid/prebid-cache).
They may not exist if the host company's cache is full, having connection problems, or other issues like that.

This is mainly intended for certain limited Prebid Mobile setups, where bids cannot be cached client-side.
If `vastxml` is present, PBS will try to add analogous keys `hb_uuid` and `hb_uuid_{bidderName}`.
In addition to the caveats above, these will exist _only if the relevant Bids are for Video_.
If they exist, the values can be used to fetch the bid's VAST XML from Prebid Cache directly.

These options are mainly intended for certain limited Prebid Mobile setups, where bids cannot be cached client-side.

#### GDPR

Expand Down
5 changes: 4 additions & 1 deletion endpoints/openrtb2/amp_auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,14 @@ func defaultRequestExt(req *openrtb.BidRequest) (errs []error) {
PriceGranularity: openrtb_ext.PriceGranularityFromString("med"),
}
}
if extRequest.Prebid.Cache == nil || extRequest.Prebid.Cache.Bids == nil {
if extRequest.Prebid.Cache == nil {
setDefaults = true
extRequest.Prebid.Cache = &openrtb_ext.ExtRequestPrebidCache{
Bids: &openrtb_ext.ExtRequestPrebidCacheBids{},
}
} else if extRequest.Prebid.Cache.Bids == nil {
setDefaults = true
extRequest.Prebid.Cache.Bids = &openrtb_ext.ExtRequestPrebidCacheBids{}
}
if setDefaults {
newExt, err := json.Marshal(extRequest)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"id": "some-request-id",
"site": {
"page": "test.somepage.com"
},
"imp": [
{
"id": "my-imp-id",
"video": {
"mimes": [
"video/mp4"
]
},
"ext": {
"appnexus": {
"placementId": 10433394
}
}
}
],
"ext": {
"prebid": {
"cache": {
"bids": {}
},
"targeting": {}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"id": "some-request-id",
"site": {
"page": "test.somepage.com"
},
"imp": [
{
"id": "my-imp-id",
"video": {
"mimes": [
"video/mp4"
]
},
"ext": {
"appnexus": {
"placementId": 10433394
}
}
}
],
"ext": {
"prebid": {
"cache": {
"vastxml": {}
}
}
}
}
83 changes: 78 additions & 5 deletions exchange/auction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package exchange

import (
"context"
"encoding/json"

"github.com/golang/glog"
"github.com/mxmCherry/openrtb"
Expand Down Expand Up @@ -54,16 +55,86 @@ func (a *auction) setRoundedPrices(priceGranularity openrtb_ext.PriceGranularity
a.roundedPrices = roundedPrices
}

func (a *auction) doCache(ctx context.Context, cache prebid_cache_client.Client) {
toCache := make([]*openrtb.Bid, 0, len(a.roundedPrices))
func (a *auction) doCache(ctx context.Context, cache prebid_cache_client.Client, bids bool, vast bool) {
if !bids && !vast {
return
}

expectNumBids := valOrZero(bids, len(a.roundedPrices))
expectNumVast := valOrZero(vast, len(a.roundedPrices))
bidIndices := make(map[int]*openrtb.Bid, expectNumBids)
vastIndices := make(map[int]*openrtb.Bid, expectNumVast)
toCache := make([]prebid_cache_client.Cacheable, 0, expectNumBids+expectNumVast)

for _, topBidsPerImp := range a.winningBidsByBidder {
for _, topBidPerBidder := range topBidsPerImp {
toCache = append(toCache, topBidPerBidder.bid)
if bids {
if jsonBytes, err := json.Marshal(topBidPerBidder.bid); err == nil {
toCache = append(toCache, prebid_cache_client.Cacheable{
Type: prebid_cache_client.TypeJSON,
Data: jsonBytes,
})
bidIndices[len(toCache)-1] = topBidPerBidder.bid
}
}
if vast && topBidPerBidder.bidType == openrtb_ext.BidTypeVideo {
vast := makeVAST(topBidPerBidder.bid)
if jsonBytes, err := json.Marshal(vast); err == nil {
toCache = append(toCache, prebid_cache_client.Cacheable{
Type: prebid_cache_client.TypeXML,
Data: jsonBytes,
})
vastIndices[len(toCache)-1] = topBidPerBidder.bid
}
}
}
}

ids := cache.PutJson(ctx, toCache)

if bids {
a.cacheIds = make(map[*openrtb.Bid]string, len(bidIndices))
for index, bid := range bidIndices {
if ids[index] != "" {
a.cacheIds[bid] = ids[index]
}
}
}
if vast {
a.vastCacheIds = make(map[*openrtb.Bid]string, len(vastIndices))
for index, bid := range vastIndices {
if ids[index] != "" {
a.vastCacheIds[bid] = ids[index]
}
}
}
}

a.cacheIds = cacheBids(ctx, cache, toCache)
// makeVAST returns some VAST XML for the given bid. If AdM is defined,
// it takes precedence. Otherwise the Nurl will be wrapped in a redirect tag.
func makeVAST(bid *openrtb.Bid) string {
if bid.AdM == "" {
return `<VAST version="3.0"><Ad><Wrapper>` +
`<AdSystem>prebid.org wrapper</AdSystem>` +
`<VASTAdTagURI><![CDATA[` + bid.NURL + `]]></VASTAdTagURI>` +
`<Impression></Impression><Creatives></Creatives>` +
`</Wrapper></Ad></VAST>`
}
return bid.AdM
}

func valOrZero(useVal bool, val int) int {
if useVal {
return val
}
return 0
}

func maybeMake(shouldMake bool, capacity int) []prebid_cache_client.Cacheable {
if shouldMake {
return make([]prebid_cache_client.Cacheable, 0, capacity)
}
return nil
}

type auction struct {
Expand All @@ -73,6 +144,8 @@ type auction struct {
winningBidsByBidder map[string]map[openrtb_ext.BidderName]*pbsOrtbBid
// roundedPrices stores the price strings rounded for each bid according to the price granularity.
roundedPrices map[*pbsOrtbBid]string
// cacheIds stores the UUIDs from Prebid Cache for each bid.
// cacheIds stores the UUIDs from Prebid Cache for fetching the full bid JSON.
cacheIds map[*openrtb.Bid]string
// vastCacheIds stores UUIDS from Prebid cache for fetching the VAST markup to video bids.
vastCacheIds map[*openrtb.Bid]string
}
31 changes: 31 additions & 0 deletions exchange/auction_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package exchange

import (
"testing"

"github.com/mxmCherry/openrtb"
"github.com/stretchr/testify/assert"
)

func TestMakeVASTGiven(t *testing.T) {
const expect = `<VAST version="3.0"></VAST>`
bid := &openrtb.Bid{
AdM: expect,
}
vast := makeVAST(bid)
assert.Equal(t, expect, vast)
}

func TestMakeVASTNurl(t *testing.T) {
const url = "http://domain.com/win-notify/1"
const expect = `<VAST version="3.0"><Ad><Wrapper>` +
`<AdSystem>prebid.org wrapper</AdSystem>` +
`<VASTAdTagURI><![CDATA[` + url + `]]></VASTAdTagURI>` +
`<Impression></Impression><Creatives></Creatives>` +
`</Wrapper></Ad></VAST>`
bid := &openrtb.Bid{
NURL: url,
}
vast := makeVAST(bid)
assert.Equal(t, expect, vast)
}
34 changes: 0 additions & 34 deletions exchange/cache.go

This file was deleted.

Loading

0 comments on commit 78ad79f

Please sign in to comment.