Skip to content

Commit

Permalink
Merge pull request #69 from datacratic/http_bidder_interface_fix
Browse files Browse the repository at this point in the history
RTBKIT-600 HttpBidderInterface: making sure that submitBids is called for all the
  • Loading branch information
oktal committed Aug 11, 2014
2 parents 71ce1ec + 533b7e5 commit 30e6f18
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 23 deletions.
73 changes: 56 additions & 17 deletions rtbkit/plugins/bidder_interface/http_bidder_interface.cc
Expand Up @@ -139,23 +139,45 @@ void HttpBidderInterface::sendAuctionMessage(std::shared_ptr<Auction> const & au
int statusCode, const std::string &, std::string &&body)
{
//cerr << "Response: " << "HTTP " << statusCode << std::endl << body << endl;

/* We need to make sure that we re-inject bids into the router for each
* agent. When receiving a BidResponse, if the SeatBid array contains
* less bids than impressions, we still need to tell "no-bid" to the
* router for the agent that did not bid, otherwise the router will
* be artificially waiting for that particular bidder to bid, and will
* expire the auction.
*/
AgentBids bidsToSubmit;
Bids bids;
bids.reserve(openRtbRequest.imp.size());
for (const auto &bidder: bidders) {
AgentBidsInfo info;
info.agentName = bidder.first;
info.agentConfig = bidder.second.agentConfig;
info.auctionId = auction->id;
info.bids = bids;
info.wcm = auction->exchangeConnector->getWinCostModel(
*auction, *info.agentConfig);
bidsToSubmit[bidder.first] = info;
}

if (errorCode != HttpClientError::None) {
router->throwException("http", "Error requesting %s: %s",
routerHost.c_str(),
httpErrorString(errorCode).c_str());
}
// If we receive a 204 No-bid, we still need to "re-inject" it to the
// router otherwise we won't expire the inFlights
else if (statusCode == 204) {
Bids bids;
bids.resize(openRtbRequest.imp.size());
fill(begin(bids), end(bids), Bid());
for (const auto &bidder: bidders) {
submitBids(bidder.first, auction->id, bids, WinCostModel());
}

// If we receive a 204 No-bid, we still need to "re-inject" it to the
// router otherwise we won't expire the inFlights
else if (statusCode == 204) {
for (auto &bidsInfo: bidsToSubmit) {
auto &info = bidsInfo.second;
fill_n(back_inserter(info.bids), openRtbRequest.imp.size(), Bid());
}

}

else if (statusCode == 200) {
else if (statusCode == 200) {
OpenRTB::BidResponse response;
ML::Parse_Context context("payload",
body.c_str(), body.size());
Expand Down Expand Up @@ -186,8 +208,8 @@ void HttpBidderInterface::sendAuctionMessage(std::shared_ptr<Auction> const & au
"Couldn't find config for externalId: %lu",
externalId);
}
ExcCheck(!agent.empty(), "Invalid agent");

Bids bids;
Bid theBid;

int crid = bid.crid.toInt();
Expand All @@ -213,15 +235,14 @@ void HttpBidderInterface::sendAuctionMessage(std::shared_ptr<Auction> const & au

theBid.spotIndex = spotIndex;

bids.push_back(std::move(theBid));

WinCostModel wcm =
auction->exchangeConnector->getWinCostModel(*auction, *config);
auto &bidInfo = bidsToSubmit[agent];
bidInfo.bids.push_back(std::move(theBid));

submitBids(agent, auction->id, bids, wcm);
}
}

}
submitBids(bidsToSubmit, openRtbRequest.imp.size());
}
);

Expand Down Expand Up @@ -384,7 +405,7 @@ bool HttpBidderInterface::prepareRequest(OpenRTB::BidRequest &request,
return true;
}

void HttpBidderInterface::submitBids(const std::string &agent, Id auctionId,
void HttpBidderInterface::injectBids(const std::string &agent, Id auctionId,
const Bids &bids, WinCostModel wcm)
{
Json::FastWriter writer;
Expand Down Expand Up @@ -413,6 +434,24 @@ void HttpBidderInterface::submitBids(const std::string &agent, Id auctionId,
router->wakeupMainLoop.signal();
}

void HttpBidderInterface::submitBids(AgentBids &info, size_t impressionsCount) {

using namespace std;
for (auto &bidsInfo: info) {

auto &bids = bidsInfo.second;
// We check whether the agent bid on all impressions. If not, then we
// complete the resopnse with no-bids because the router is actually
// asserting on the size of the bids array matching the size of
// the impressions object
const size_t diff = impressionsCount - bids.bids.size();
if (diff > 0) {
fill_n(back_inserter(bids.bids), diff, Bid());
}
injectBids(bidsInfo.first, bids.auctionId, bids.bids, bids.wcm);
}
}

//
// factory
//
Expand Down
25 changes: 19 additions & 6 deletions rtbkit/plugins/bidder_interface/http_bidder_interface.h
Expand Up @@ -68,12 +68,17 @@ struct HttpBidderInterface : public BidderInterface
static Logging::Category trace;

private:
bool prepareRequest(OpenRTB::BidRequest &request,
const RTBKIT::BidRequest &originalRequest,
const std::shared_ptr<Auction> &auction,
const std::map<std::string, BidInfo> &bidders) const;
void submitBids(const std::string &agent, Id auctionId,
const Bids &bids, WinCostModel wcm);

struct AgentBidsInfo {
std::shared_ptr<const AgentConfig> agentConfig;
std::string agentName;
Id auctionId;
Bids bids;
WinCostModel wcm;
};

typedef std::map<std::string, AgentBidsInfo> AgentBids;

MessageLoop loop;
std::shared_ptr<HttpClient> httpClientRouter;
std::shared_ptr<HttpClient> httpClientAdserverWins;
Expand All @@ -84,6 +89,14 @@ struct HttpBidderInterface : public BidderInterface
uint16_t adserverWinPort;
uint16_t adserverEventPort;

void submitBids(AgentBids &info, size_t impressionsCount);
bool prepareRequest(OpenRTB::BidRequest &request,
const RTBKIT::BidRequest &originalRequest,
const std::shared_ptr<Auction> &auction,
const std::map<std::string, BidInfo> &bidders) const;
void injectBids(const std::string &agent, Id auctionId,
const Bids &bids, WinCostModel wcm);

};

}
Expand Down

0 comments on commit 30e6f18

Please sign in to comment.