func()

in projects/gke-optimization/binpacker/api/pkg/interface/handler/binpacking.go [70:151]


func (bh binpackingHandler) Calculate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	m := protojson.MarshalOptions{
		EmitUnpopulated: true,
	}
	body, err := io.ReadAll(r.Body)
	if err != nil {
		calculateErrorResponse(w, m, "failed to read request json", err.Error(), err)
		return
	}

	var request pb.BinpackingCalculateRequest
	err = protojson.Unmarshal(body, &request)
	if err != nil {
		calculateErrorResponse(w, m, "invalid data provided", err.Error(), err)
		return
	}

	if len(request.Workloads) == 0 {
		calculateErrorResponse(w, m, "invalid data provided", "no workload provided", err)
		return
	}
	if request.MinNumNodes == 0 {
		request.MinNumNodes = 1
	}

	metrics := extractMetrics(&request)

	ctx := context.Background()
	solution, err := bh.binpackingUsecase.Calculate(
		ctx,
		metrics.CPURequests,
		metrics.CPULimits,
		metrics.MemoryRequests,
		metrics.MemoryLimits,
		metrics.MinNumNode,
	)
	if err != nil {
		calculateErrorResponse(w, m, "failed to find solution", err.Error(), err)
		return
	}

	response, err := m.Marshal(&pb.BinpackingCalculateResponse{
		Recommendation: &pb.BinpackingRecommendation{
			Cpu:      float64(solution.Recommendation.CPU),
			Memory:   float64(solution.Recommendation.MemoryInGiB),
			NumNodes: int32(solution.Recommendation.NumNodes),
		},
		RequestDetail: &pb.BinpackingRequestDetail{
			TotalCpuRequest:    float64(solution.Rationale.CPU.TotalCPURequest),
			MaxCpuLimit:        float64(solution.Rationale.CPU.MaxCPULimit),
			TotalMemoryRequest: int64(solution.Rationale.Memory.TotalMemoryRequest),
			MaxMemoryLimit:     int64(solution.Rationale.Memory.MaxMemoryLimit),
		},
		RecommendationBreakdown: &pb.RecommendationBreakdown{
			Cpu: &pb.CpuBreakdown{
				NodeSize:              float64(solution.Recommendation.CPU),
				Reserved:              float64(solution.Rationale.CPU.Reserved),
				SystemUsage:           float64(solution.Rationale.CPU.SystemResourcesUsage),
				CapacityUserWorkloads: float64(solution.Rationale.CPU.CapacityUserWorkloads),
			},
			Memory: &pb.MemoryBreakdown{
				NodeSize:              int64(node.GiBToBytes(solution.Recommendation.MemoryInGiB)),
				KernelUsage:           int64(solution.Rationale.Memory.KernelUsage),
				Reserved:              int64(solution.Rationale.Memory.Reserved),
				EvictionThreshold:     int64(solution.Rationale.Memory.EvictionThreshold),
				SystemUsage:           int64(solution.Rationale.Memory.SystemResourcesUsage),
				CapacityUserWorkloads: int64(solution.Rationale.Memory.CapacityUserWorkloads),
			},
		},
	})

	if err != nil {
		calculateErrorResponse(w, m, "failed to encode json", err.Error(), err)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	_, writeErr := w.Write(response)
	if writeErr != nil {
		glog.Errorf("Failed to write response: %s", response)
	}
}