adservice: find relevant ads by category (#61)

The ad service now returns ads matching the categories of the product that is
currently displayed.  Changes in this commit:

- List all products' categories in products.json.

- Pass the current product's categories from the frontend to the ad service when
  looking up ads.

- Store a statically initialized multimap from product category to ad in the ad
  service.

- Return all ads matching the given categories when handling an ads request.
  The ad service continues to return random ads when no categories are given or
  no ads match the categories.
This commit is contained in:
sebright 2018-10-01 22:44:56 -07:00 committed by Ahmet Alp Balkan
parent 86c8c06cc1
commit dc7effd601
11 changed files with 1532 additions and 925 deletions

View file

@ -26,17 +26,6 @@
revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0"
[[projects]]
branch = "master"
digest = "1:3ef905a7059a17712b7b27315692992f84f356e828d38f6ff0624e04103ec675"
name = "github.com/GoogleCloudPlatform/microservices-demo"
packages = [
"src/frontend/genproto",
"src/frontend/money",
]
pruneopts = "UT"
revision = "6d969441585ade8c91c235115c7cdb12ac61354f"
[[projects]]
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
name = "github.com/golang/protobuf"

View file

@ -33,10 +33,6 @@
name = "contrib.go.opencensus.io/exporter/stackdriver"
version = "0.5.0"
[[constraint]]
branch = "master"
name = "github.com/GoogleCloudPlatform/microservices-demo"
[[constraint]]
name = "github.com/golang/protobuf"
version = "1.2.0"

View file

@ -80,7 +80,7 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
"products": ps,
"cart_size": len(cart),
"banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments
"ad": fe.chooseAd(r.Context(), log),
"ad": fe.chooseAd(r.Context(), []string{}, log),
}); err != nil {
log.Error(err)
}
@ -133,7 +133,7 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"ad": fe.chooseAd(r.Context(), log),
"ad": fe.chooseAd(r.Context(), p.Categories, log),
"user_currency": currentCurrency(r),
"currencies": currencies,
"product": product,
@ -346,8 +346,8 @@ func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Requ
// chooseAd queries for advertisements available and randomly chooses one, if
// available. It ignores the error retrieving the ad since it is not critical.
func (fe *frontendServer) chooseAd(ctx context.Context, log logrus.FieldLogger) *pb.Ad {
ads, err := fe.getAd(ctx)
func (fe *frontendServer) chooseAd(ctx context.Context, ctxKeys []string, log logrus.FieldLogger) *pb.Ad {
ads, err := fe.getAd(ctx, ctxKeys)
if err != nil {
log.WithField("error", err).Warn("failed to retrieve ads")
return nil

View file

@ -116,12 +116,12 @@ func (fe *frontendServer) getRecommendations(ctx context.Context, userID string,
return out, err
}
func (fe *frontendServer) getAd(ctx context.Context) ([]*pb.Ad, error) {
func (fe *frontendServer) getAd(ctx context.Context, ctxKeys []string) ([]*pb.Ad, error) {
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
defer cancel()
resp, err := pb.NewAdServiceClient(fe.adSvcConn).GetAds(ctx, &pb.AdRequest{
ContextKeys: nil,
ContextKeys: ctxKeys,
})
return resp.GetAds(), errors.Wrap(err, "failed to get ads")
}