Skip to content

Creating bidder

Vladimir Venediktov edited this page Jun 11, 2017 · 13 revisions

Creating bidder is a 5 minute task

using DSLT = DSL::GenericDSL<> ;
exchange_handler<DSLT> openrtb_handler(std::chrono::milliseconds(50))
    .logger([](const std::string &data) {
        LOG(debug) << "request data :" << data ;
    })
    .error_logger([](const std::string &data) {
        LOG(debug) << "request error :" << data ;
    })
    .auction_async([](const auto &request) {
        //respond with no bid
        return  BidResponse();
    });

vanilla-rtb is using DSL mappers for conversion from json request to C++ structures.

as long as your custom mapper defines 3 types

 deserialized_type
 serialized_type
 parse_error_type

it should work with our GenericDSL class listed below.

  template<typename T=std::string , template<class> class Mapper = DSL::dsl_mapper, unsigned int Size=128>
  class GenericDSL : public Mapper<T>  {
            
  public:
      using deserialized_type = typename Mapper<T>::deserialized_type;
      using serialized_type = typename Mapper<T>::serialized_type;
      using parse_error_type = typename Mapper<T>::parse_error_type;

vanilla-rtb works with any version of openRTB , so for example if you want to use our stack with both openRTB 2.5 and also continue support to openRTB 2.2 we provided, create your own in the new namespace DSL::v25::CustomDSL and add

exchange handler to the same executable by providing different CRUD endpoint or run it in a separate process listening on a different port.

using DSLT = DSL::GenericDSL<> ;
exchange_handler<DSLT> openrtb_handler(std::chrono::milliseconds(40));
    openrtb_handler    
    .logger([](const std::string &data) {
        LOG(debug) << "request v2.2 data:" << data ;
    })
    .error_logger([](const std::string &data) {
        LOG(debug) << "request v2.2 error: " << data ;
    })
    .auction_async([](const auto &request) {
        return  BidResponse();
});

using DSLT25 = DSL::GenericDSL<std::string, dsl_mapper_25> ; //dsl_mapper_25 is your custom mapper based on v.2.5
exchange_handler<DSLT25> openrtb_handler_25(std::chrono::milliseconds(40));
    openrtb_handler_25
    .logger([](const std::string &data) {
        LOG(debug) << "request v2.5 data:" << data ;
    })
    .error_logger([](const std::string &data) {
        LOG(debug) << "request v2.5 error: " << data ;
    })
    .auction_async([](const auto &request) {
        return  BidResponse();
});

Please visit wiki Customizing-BidRequest-and-BidResponse

Create CRUD handlers for your 2.2 and 2.5 exchange handlers

 restful_dispatcher_t dispatcher(ep.root) ;
    dispatcher.crud_match(std::string("/openrtb_handler/auction/"))
              .post([&](http::server::reply & r, const http::crud::crud_match<boost::cmatch> & match) {
                  openrtb_handler.handle_post(r,match);
              });
    dispatcher.crud_match(std::string("/openrtb_handler/v25/auction/"))
              .post([&](http::server::reply & r, const http::crud::crud_match<boost::cmatch> & match) {
                  openrtb_handler_25.handle_post(r,match);
});

To make your stack outperform you should use zero-copy , zero-memory allocation , so to achieve that we have coded our DSL mapper as a template class accepting string_view structure used for BidRequest strings as a template parameter, so when string_view is passed to DSL mapper , the mapper does not allocate memory on the heap or copy bytes from original incoming json data into the the string.

 using DSLT = DSL::GenericDSL<jsonv::string_view> ; 
 using DSLT25 = DSL::GenericDSL<jsonv::string_view, dsl_mapper_25> ;

The string_view is a string structure having no ownership of the data and it can be passed to functions by copy as it represents begin address of a string and the size of string. Few things to remember though , because it does not own memory the actual string it points to has to be valid for the life time of your string_view.