You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.6 KiB

package clientserver
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"math"
"net/http"
customtypes "sample-choose-ad/cmd/custom_types"
req_types "sample-choose-ad/cmd/requests_types"
"sort"
"time"
)
func sendRequest(url string, body *io.Reader) (req_types.SuccesResponse, error) {
var pResp req_types.SuccesResponse
c := &http.Client{
Timeout: 200 * time.Millisecond,
}
resp, err := c.Post(url, "application/json", *body)
if err != nil {
log.Println(err)
eText := fmt.Sprintf("%v\n not responding", url)
return pResp, errors.New(eText)
}
defer resp.Body.Close()
if resp.StatusCode == 204 {
return pResp, errors.New("No content")
}
b, _ := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(b, &pResp)
if err != nil {
log.Println(err)
}
return pResp, nil
}
// Create requset body based in incoming reqest `ir` and return
// `OutgoingRequest` as bytes.Reader from marshaled JSON
func constructPartnersRequestBody(ir *req_types.IncomingRequest) io.Reader {
var outReqBody req_types.OutgoingRequest
var imps []req_types.Imp
// WARN: uint and float multiplication may cause problems
for _, tile := range ir.Tiles {
imps = append(imps, req_types.Imp{
Id: tile.Id,
Minwidth: tile.Width,
Minheight: uint(math.Floor(float64(tile.Width * uint(tile.Ratio))))})
}
outReqBody.Id = *ir.Id
outReqBody.Imp = imps
outReqBody.Context = ir.Context
t, _ := json.Marshal(outReqBody)
return bytes.NewReader(t)
}
// map[imp.id]map[imp.id.price]
type PartnersResponses map[uint]map[float64]req_types.RespImp
// Make request for each partner and returns
func makePartnersRequests(partners []customtypes.PartnersAddress, ir *req_types.IncomingRequest) {
p_body := constructPartnersRequestBody(ir)
// Two data structures:
// partnersRespones for getting price with O(1) complexity
// []prices as slice of actual prices
partnersRespones := make(map[uint]map[float64]req_types.RespImp)
prices := make(map[uint][]float64)
for _, p := range partners {
url := fmt.Sprintf("http://%v:%v/%v", p.Ip, p.Port, PARTNER_ENDPOINT)
re, err := sendRequest(url, &p_body)
if err != nil {
log.Println(err)
continue
}
// append only successful responses
for _, r := range re.Imp {
if partnersRespones[r.Id] == nil {
partnersRespones[r.Id] = make(map[float64]req_types.RespImp)
}
partnersRespones[r.Id][r.Price] = r
prices[r.Id] = append(prices[r.Id], r.Price)
}
}
if len(partnersRespones) == 0 {
log.Println("Error: no responses from partners.")
return
}
// Sorting prices, now biggest price at index len-1
for _, p := range prices {
sort.Float64s(p)
}
}