Changed product catalog to use json, so that it slows down and generates nice profiles
This commit is contained in:
parent
2713f47bbb
commit
dbc9523cea
1 changed files with 128 additions and 75 deletions
|
@ -10,7 +10,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
pb "./genproto"
|
pb "./genproto"
|
||||||
|
|
||||||
"cloud.google.com/go/profiler"
|
"cloud.google.com/go/profiler"
|
||||||
|
"github.com/golang/protobuf/jsonpb"
|
||||||
"go.opencensus.io/exporter/stackdriver"
|
"go.opencensus.io/exporter/stackdriver"
|
||||||
"go.opencensus.io/plugin/ocgrpc"
|
"go.opencensus.io/plugin/ocgrpc"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
|
@ -21,71 +23,107 @@ import (
|
||||||
|
|
||||||
var port = flag.Int("port", 3550, "port to listen at")
|
var port = flag.Int("port", 3550, "port to listen at")
|
||||||
|
|
||||||
var catalog = []*pb.Product{
|
const catalogJSON = `{
|
||||||
{
|
"products": [
|
||||||
Id: "OLJCESPC7Z",
|
{
|
||||||
Name: "Vintage Typewriter",
|
"id": "OLJCESPC7Z",
|
||||||
Description: "This typewriter looks good in your living room.",
|
"name": "Vintage Typewriter",
|
||||||
Picture: "/static/img/products/typewriter.jpg",
|
"description": "This typewriter looks good in your living room.",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 67, Nanos: 990000000},
|
"picture": "/static/img/products/typewriter.jpg",
|
||||||
},
|
"priceUsd": {
|
||||||
{
|
"currencyCode": "USD",
|
||||||
Id: "66VCHSJNUP",
|
"units": 67,
|
||||||
Name: "Vintage Camera Lens",
|
"nanos": 990000000
|
||||||
Description: "You won't have a camera to use it and it probably doesn't work anyway.",
|
}
|
||||||
Picture: "/static/img/products/camera-lens.jpg",
|
},
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 12, Nanos: 490000000},
|
{
|
||||||
},
|
"id": "66VCHSJNUP",
|
||||||
{
|
"name": "Vintage Camera Lens",
|
||||||
Id: "1YMWWN1N4O",
|
"description": "You won't have a camera to use it and it probably doesn't work anyway.",
|
||||||
Name: "Home Barista Kit",
|
"picture": "/static/img/products/camera-lens.jpg",
|
||||||
Description: "Always wanted to brew coffee with Chemex and Aeropress at home?",
|
"priceUsd": {
|
||||||
Picture: "/static/img/products/barista-kit.jpg",
|
"currencyCode": "USD",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 124, Nanos: 0},
|
"units": 12,
|
||||||
},
|
"nanos": 490000000
|
||||||
{
|
}
|
||||||
Id: "L9ECAV7KIM",
|
},
|
||||||
Name: "Terrarium",
|
{
|
||||||
Description: "This terrarium will looks great in your white painted living room.",
|
"id": "1YMWWN1N4O",
|
||||||
Picture: "/static/img/products/terrarium.jpg",
|
"name": "Home Barista Kit",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 36, Nanos: 450000000},
|
"description": "Always wanted to brew coffee with Chemex and Aeropress at home?",
|
||||||
},
|
"picture": "/static/img/products/barista-kit.jpg",
|
||||||
{
|
"priceUsd": {
|
||||||
Id: "2ZYFJ3GM2N",
|
"currencyCode": "USD",
|
||||||
Name: "Film Camera",
|
"units": 124
|
||||||
Description: "This camera looks like it's a film camera, but it's actually digital.",
|
}
|
||||||
Picture: "/static/img/products/film-camera.jpg",
|
},
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 2245, Nanos: 00000000},
|
{
|
||||||
},
|
"id": "L9ECAV7KIM",
|
||||||
{
|
"name": "Terrarium",
|
||||||
Id: "0PUK6V6EV0",
|
"description": "This terrarium will looks great in your white painted living room.",
|
||||||
Name: "Vintage Record Player",
|
"picture": "/static/img/products/terrarium.jpg",
|
||||||
Description: "It still works.",
|
"priceUsd": {
|
||||||
Picture: "/static/img/products/record-player.jpg",
|
"currencyCode": "USD",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 65, Nanos: 500000000},
|
"units": 36,
|
||||||
},
|
"nanos": 450000000
|
||||||
{
|
}
|
||||||
Id: "LS4PSXUNUM",
|
},
|
||||||
Name: "Metal Camping Mug",
|
{
|
||||||
Description: "You probably don't go camping that often but this is better than plastic cups.",
|
"id": "2ZYFJ3GM2N",
|
||||||
Picture: "/static/img/products/camp-mug.jpg",
|
"name": "Film Camera",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 24, Nanos: 330000000},
|
"description": "This camera looks like it's a film camera, but it's actually digital.",
|
||||||
},
|
"picture": "/static/img/products/film-camera.jpg",
|
||||||
{
|
"priceUsd": {
|
||||||
Id: "9SIQT8TOJO",
|
"currencyCode": "USD",
|
||||||
Name: "City Bike",
|
"units": 2245
|
||||||
Description: "This single gear bike probably cannot climb the hills of San Francisco.",
|
}
|
||||||
Picture: "/static/img/products/city-bike.jpg",
|
},
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 789, Nanos: 500000000},
|
{
|
||||||
},
|
"id": "0PUK6V6EV0",
|
||||||
{
|
"name": "Vintage Record Player",
|
||||||
Id: "6E92ZMYYFZ",
|
"description": "It still works.",
|
||||||
Name: "Air Plant",
|
"picture": "/static/img/products/record-player.jpg",
|
||||||
Description: "Have you ever wondered whether air plants need water? Buy one and figure out.",
|
"priceUsd": {
|
||||||
Picture: "/static/img/products/air-plant.jpg",
|
"currencyCode": "USD",
|
||||||
PriceUsd: &pb.Money{CurrencyCode: "USD", Units: 12, Nanos: 300000000},
|
"units": 65,
|
||||||
},
|
"nanos": 500000000
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "LS4PSXUNUM",
|
||||||
|
"name": "Metal Camping Mug",
|
||||||
|
"description": "You probably don't go camping that often but this is better than plastic cups.",
|
||||||
|
"picture": "/static/img/products/camp-mug.jpg",
|
||||||
|
"priceUsd": {
|
||||||
|
"currencyCode": "USD",
|
||||||
|
"units": 24,
|
||||||
|
"nanos": 330000000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9SIQT8TOJO",
|
||||||
|
"name": "City Bike",
|
||||||
|
"description": "This single gear bike probably cannot climb the hills of San Francisco.",
|
||||||
|
"picture": "/static/img/products/city-bike.jpg",
|
||||||
|
"priceUsd": {
|
||||||
|
"currencyCode": "USD",
|
||||||
|
"units": 789,
|
||||||
|
"nanos": 500000000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6E92ZMYYFZ",
|
||||||
|
"name": "Air Plant",
|
||||||
|
"description": "Have you ever wondered whether air plants need water? Buy one and figure out.",
|
||||||
|
"picture": "/static/img/products/air-plant.jpg",
|
||||||
|
"priceUsd": {
|
||||||
|
"currencyCode": "USD",
|
||||||
|
"units": 12,
|
||||||
|
"nanos": 300000000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
go initTracing()
|
go initTracing()
|
||||||
|
@ -136,36 +174,51 @@ func initProfiling(service, version string) {
|
||||||
Service: service,
|
Service: service,
|
||||||
ServiceVersion: version,
|
ServiceVersion: version,
|
||||||
// ProjectID must be set if not running on GCP.
|
// ProjectID must be set if not running on GCP.
|
||||||
// ProjectID: "my-project",
|
ProjectID: "oval-time-515",
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Printf("warn: failed to start profiler: %+v", err)
|
log.Printf("warn: failed to start profiler: %+v", err)
|
||||||
|
d := time.Second * 10 * time.Duration(i)
|
||||||
|
log.Printf("sleeping %v to retry initializing stackdriver profiler", d)
|
||||||
|
time.Sleep(d)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
d := time.Second * 10 * time.Duration(i)
|
return
|
||||||
log.Printf("sleeping %v to retry initializing stackdriver profiler", d)
|
|
||||||
time.Sleep(d)
|
|
||||||
}
|
}
|
||||||
log.Printf("warning: could not initialize stackdriver profiler after retrying, giving up")
|
log.Printf("warning: could not initialize stackdriver profiler after retrying, giving up")
|
||||||
}
|
}
|
||||||
|
|
||||||
type productCatalog struct{}
|
type productCatalog struct{}
|
||||||
|
|
||||||
|
func (p *productCatalog) catalog() []*pb.Product {
|
||||||
|
var cat pb.ListProductsResponse
|
||||||
|
if err := jsonpb.UnmarshalString(catalogJSON, &cat); err != nil {
|
||||||
|
log.Printf("warning: failed to parse the product catalog: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return cat.Products
|
||||||
|
}
|
||||||
|
|
||||||
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
|
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
|
||||||
return &pb.ListProductsResponse{Products: catalog}, nil
|
return &pb.ListProductsResponse{Products: p.catalog()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
|
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
|
||||||
for _, p := range catalog {
|
var found *pb.Product
|
||||||
if req.Id == p.Id {
|
for i := 0; i < len(p.catalog()); i++ {
|
||||||
return p, nil
|
if req.Id == p.catalog()[i].Id {
|
||||||
|
found = p.catalog()[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, status.Errorf(codes.NotFound, "no product with ID %s", req.Id)
|
if found == nil {
|
||||||
|
return nil, status.Errorf(codes.NotFound, "no product with ID %s", req.Id)
|
||||||
|
}
|
||||||
|
return found, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
|
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
|
||||||
// Intepret query as a substring match in name or description.
|
// Intepret query as a substring match in name or description.
|
||||||
var ps []*pb.Product
|
var ps []*pb.Product
|
||||||
for _, p := range catalog {
|
for _, p := range p.catalog() {
|
||||||
if strings.Contains(strings.ToLower(p.Name), strings.ToLower(req.Query)) ||
|
if strings.Contains(strings.ToLower(p.Name), strings.ToLower(req.Query)) ||
|
||||||
strings.Contains(strings.ToLower(p.Description), strings.ToLower(req.Query)) {
|
strings.Contains(strings.ToLower(p.Description), strings.ToLower(req.Query)) {
|
||||||
ps = append(ps, p)
|
ps = append(ps, p)
|
||||||
|
|
Loading…
Reference in a new issue