Giter Club home page Giter Club logo

bidding-system's Introduction

Build Status Coverage Status CodeFactor Codacy Badge Codacy Badge Lines of code Docker Image Size (latest by date)

Bidding system

Yieldlab is a technology service provider, connecting suppliers (those who have space to show ads, e.g. on their websites) to bidders (those who actually want to show ads). The core process is to listen for requests, gather metadata and bids, and afterwards to determine who is winning. This challenge is about setting up a simplified version of this core process as its own application.

Contents of this document:

1 The task

Build a bidding system behaving as following:

For every incoming request as described in 1, send out bid requests as described in 2 to a configurable number of bidders [5]. Responses from these bidders as described in 3 must be processed. The highest bidder wins, and payload is sent out as described in 4.

Incoming and outgoing communication is to be done over HTTP. Message formats are described below.

Please write code that you would want to maintain in production as well, or document all exceptions to this rule and give reasons as to why you made those exceptions.

Please stay with commonly known frameworks for easier reviewing and explaining afterwards.

1.1 Incoming Requests

The application must listen to incoming HTTP requests on port 8080.

An incoming request is of the following format:

http://localhost:8080/[id]?[key=value,...]

The URL will contain an ID to identify the ad for the auction, and a number of query-parameters.

1.2 Bid Requests

The application must forward incoming bid requests by sending a corresponding HTTP POST request to each of the configured bidders with the body in the following JSON format:

{
	“id”: $id,
	“attributes” : {
		“$key”: “$value”,
		
	}
}

The property attributes must contain all incoming query-parameters. Multi-value parameters need not be supported. Test is after starting the bidders using the scripts/test-setup.sh script, then send some json file:

http POST localhost:[8081|8082|8083] < src/main/resources/bidders-request-[1|2|3|4|5|6|7|8|9|10|11].json

1.3 Bid Response

The bidders' response will contain details of the bid(offered price), with id and bid values in a numeric format:

{
	"id" : $id,
	"bid": bid,
	"content": "the string to deliver as a response"
}

1.4 Auction Response

The response for the auction must be the content property of the winning bid, with some tags that can be mentioned in the content replaced with respective values.

For now, only $price$ must be supported, denoting the final price of the bid.

Example:

Following bid responses:

{
	"id" : 123,
	"bid": 750,
	"content": "a:$price"
}

and

{
	"id" : 123,
	"bid": 500,
	"content": "b:$price"
}

will produce auction response as string: a:750

1.5 Configuration

The application should have means to accept accept a number of configuration parameters. For the scope of this task, only one parameter is to be supported:

Parameter Meaning
bidders a comma-separated list of URLs denoting bidder endpoints

2 How to test your application

In order to test your application for correctness, a simple test suite is provided.

2.1 Prerequisites

First, a set of bidders is required that will respoond to bidding requests sent out by your application. For this test suite, we will be using a pre-built Docker image that will be started several times with sligthly different configuration values.

Moreover, we provide a shell script that executes the tests and verifies the test results. That shell script requires the curl and diff binaries to be in your PATH.

So, here is a list of the requirements:

2.2 Start the Docker containers

To start the test environment, either use the script test-setup.sh or run the following commands one after the other from your shell:

docker run --rm -e server.port=8081 -e biddingTrigger=a -e initial=150 -p 8081:8081 yieldlab/recruiting-test-bidder &
docker run --rm -e server.port=8082 -e biddingTrigger=b -e initial=250 -p 8082:8082 yieldlab/recruiting-test-bidder &
docker run --rm -e server.port=8083 -e biddingTrigger=c -e initial=500 -p 8083:8083 yieldlab/recruiting-test-bidder &

This will set up three bidders on localhost, opening ports 8081, 8082 and 8083.

2.3 Start the application

You can use the following configuration parameters to connect to these bidders from your application:

Parameter Value
bidders http://localhost:8081, http://localhost:8082, http://localhost:8083

2.4 Run the test

To run the test, execute the shell script run-test.sh. The script expects your application to listen on localhost:8080. It will issue a number of bid requests to your application and verify the responses to these requests. If your application doesn't respond correctly, it will print out a diff between the expected and the actual results.

3 Bidding system in action

3.1 Requirements

  • JDK version 1.8+
  • scala version 2.12+
  • sbt version 1.4.7+

3.2 Quick test

After start the bidders using the script test-setup.sh, start the Bidding system by running the following command. Please use ", the argument name --bidders. and separate the bidders by a single , without spaces.

sbt "run --bidders http://localhost:8081,http://localhost:8082,http://localhost:8083"

Run the generic test using the script run-test.sh and make sure that the 3 bidders are running.

3.2.1 Basic commands:

  • Compiling: sbt compile.
  • Compiling & Running: sbt "run --bidders http://localhost:8081,http://localhost:8082,http://localhost:8083".
  • Unit tests: sbt test.
  • Generate documentation: sbt doc, then open the target/scala-2.12/api/index.html file.

3.3 Fault tolerant system

The Bidding system accepts bidders using a fault tolerance approach. In case that some or all bidders passed as argument to the Bidding System are not available, the Bidden System will compute the highest bid based on the bidders that are responding before 5 seconds. If the answer of a bidder last more than 5 seconds it will be considered a null bid and will not be processed. Hence, the bid request will never fail, regardless there are bidders available or not. Test it by killing some bidder(s) already running (i.e., that were passed in the argument list) and issue single HTTP GET command available at the script run-test.sh. The bid offer may change depending on the bidders that are available.

3.4 Docker image

We use the sbt-native-packager to generate the Docker image of the Bidding System.

sbt docker:stage
sbt docker:publishLocal
docker images
 
REPOSITORY                        TAG                     IMAGE ID       CREATED          SIZE
felipeogutierrez/bidding-system   0.1                     5284993293f2   20 seconds ago   127MB

docker run --rm --add-host host.docker.internal:host-gateway -i -p 8080:8080 felipeogutierrez/bidding-system:0.1 --bidders http://host.docker.internal:8081,http://host.docker.internal:8082,http://host.docker.internal:8083

docker image rm -f IMAGE_ID

3.5 Kubernetes

TODO: the kube-file to start the bidders containers using docker are not starting using kubernetes. This is happening because the parameters "server.port=8081 biddingTrigger=a initial=150" are not recognized by the docker image inside Kubernetes. Therefore, all the bidders start on the default mode on port 8081 and we cannot have a winner bid in this environment.

$ minikube start --cpus 4 --memory 8192
$ kubectl create namespace bidding-system
$ kubectl apply -f k8s/bidders-pod.yaml -n bidding-system
$ kubectl apply -f k8s/bidding-auction-system-pod.yaml -n bidding-system
$ kubectl -n bidding-system port-forward bidding-auction-pod 8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
kubectl get services -A
kubectl get pods -A
kubectl -n bidding-system logs -f bidder-01-0
kubectl -n bidding-system logs -f bidder-02-0
kubectl -n bidding-system logs -f bidder-03-0
kubectl -n bidding-system logs -f bidding-auction-pod
kubectl -n bidding-system exec -i -t bidding-auction-pod -- /bin/ash


kubectl -n bidding-system delete pods bidder-01-0
kubectl -n bidding-system delete pods bidder-02-0
kubectl -n bidding-system delete pods bidder-03-0
kubectl -n bidding-system delete pods bidding-auction-pod
kubectl delete namespace bidding-system

bidding-system's People

Contributors

codacy-badger avatar felipegutierrez avatar

Watchers

 avatar  avatar

bidding-system's Issues

The docker image of the bidders are not accepting arguments from a hube file

The file k8s/bidders-pod.yaml is used to launch the bidders to the minikube cluster. We use the same command of the file test-setup.sh:

docker run --rm -e server.port=8081 -e biddingTrigger=a -e initial=150 -p 8081:8081 yieldlab/recruiting-test-bidder &
docker run --rm -e server.port=8082 -e biddingTrigger=b -e initial=250 -p 8082:8082 yieldlab/recruiting-test-bidder &
docker run --rm -e server.port=8083 -e biddingTrigger=c -e initial=500 -p 8083:8083 yieldlab/recruiting-test-bidder &

But the docker image is not accepting the arguments -e server.port=8082 -e biddingTrigger=b -e initial=250 -p 8082:8082 that are necessary to launch the bidders on different ports: 8081, 8082, and 8083. The error is: No active profile set, falling back to default profiles: default

The full stack trace error is:

$ kubectl -n bidding-system logs -f bidder-02-0

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.2.RELEASE)

2021-02-24 14:31:55.979  INFO 1 --- [           main] d.yieldlab.recruiting.rtb.bidder.Bidder  : Starting Bidder on bidder-02-0.bidder-02-service.bidding-system.svc.cluster.local with PID 1 (/bidder-1.0-SNAPSHOT.jar started by root in /)
2021-02-24 14:31:55.984  INFO 1 --- [           main] d.yieldlab.recruiting.rtb.bidder.Bidder  : No active profile set, falling back to default profiles: default
2021-02-24 14:31:56.081  INFO 1 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@20f6f473: startup date [Wed Feb 24 14:31:56 UTC 2021]; root of context hierarchy
2021-02-24 14:31:57.439  INFO 1 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2021-02-24 14:32:00.001  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8081 (http)
2021-02-24 14:32:00.072  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2021-02-24 14:32:00.074  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.30
2021-02-24 14:32:00.466  INFO 1 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-02-24 14:32:01.412  INFO 1 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2021-02-24 14:32:01.418  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2021-02-24 14:32:01.419  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2021-02-24 14:32:01.419  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2021-02-24 14:32:01.420  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2021-02-24 14:32:03.358  INFO 1 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2021-02-24 14:32:03.693  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8081 (http)
2021-02-24 14:32:03.704  INFO 1 --- [           main] d.yieldlab.recruiting.rtb.bidder.Bidder  : Started Bidder in 8.266 seconds (JVM running for 8.764)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.