Commit 24a00f24 authored by Mohamad Bashar Desoki's avatar Mohamad Bashar Desoki

Open-Prediction Scaler

parent ea667aca
package scalers
import (
"context"
"fmt"
"log"
"strconv"
"time"
"github.com/go-logr/logr"
"github.com/go-playground/validator/v10"
"github.com/xhit/go-str2duration/v2"
v2 "k8s.io/api/autoscaling/v2"
"k8s.io/metrics/pkg/apis/external_metrics"
kedautil "github.com/kedacore/keda/v2/pkg/util"
"github.com/mhdbashar/prediction-go/prediction"
"google.golang.org/grpc"
"github.com/prometheus/client_golang/api"
v1 "github.com/prometheus/client_golang/api/prometheus/v1"
"github.com/prometheus/common/model"
)
const (
openPredictionMetricType = "External"
openPredictionMetricPrefix = "openPrediction_metric"
)
var (
default_step = "15m"
)
type openPredictionScaler struct {
metrictype v2.MetricTargetType
metadata *openPredictionMetadata
prometheusClient api.Client
api v1.API
grpcConn *grpc.ClientConn
grpcClient prediction.PredictionServiceClient
logger logr.Logger
}
type openPredictionMetadata struct {
history string
stepDuration string
verticalWindow int
horizontalWindow int
prometheusAddress string
predictionServiceAddress string
query string
threshold float64
activationThreshold float64
scalerIndex int
}
func (s *openPredictionScaler) setupClientConn(predictionServiceAddress string) error {
conn, err := grpc.Dial(predictionServiceAddress, grpc.WithInsecure())
if err != nil {
log.Fatalf("Failed to connect: %v", err)
return err
}
s.grpcConn = conn
client := prediction.NewPredictionServiceClient(conn)
s.grpcClient = client
return err
}
func NewopenPredictionScaler(ctx context.Context, config *ScalerConfig) (Scaler, error) {
// logger metrictype metadata prometheusClie api grpcConn grpcClient
s := &openPredictionScaler{}
// logger
logger := InitializeLogger(config, "openPrediction_scaler")
s.logger = logger
// metrictype
metrictype, err := GetMetricTargetType(config)
if err != nil {
logger.Error(err, "error getting scaler metric type")
return nil, fmt.Errorf("error getting scaler metric type: %w", err)
}
s.metrictype = metrictype
// metadata
meta, err := parseOpenPredictionMetaData(config)
if err != nil {
return nil, fmt.Errorf("error parsing OpenPrediction metadata: %s", err)
}
s.metadata = meta
// prometheusClient api
err = s.initOpenPredictionPrometheusConn(ctx)
if err != nil {
logger.Error(err, "error create Prometheus client and API objects")
return nil, fmt.Errorf("error create Prometheus client and API objects: %3s", err)
}
// grpcConn grpcClient
err = s.setupClientConn(meta.predictionServiceAddress)
if err != nil {
logger.Error(err, "error init GRPC client")
return nil, fmt.Errorf("error init GRPC client: %3s", err)
}
return s, nil
}
func parseOpenPredictionMetaData(config *ScalerConfig) (result *openPredictionMetadata, err error) {
validate := validator.New()
meta := openPredictionMetadata{}
//history
if val, ok := config.TriggerMetadata["history"]; ok {
if len(val) == 0 {
return nil, fmt.Errorf("no history given")
}
meta.history = val
} else {
return nil, fmt.Errorf("no history given")
}
//stepDuration
if val, ok := config.TriggerMetadata["stepDuration"]; ok {
if len(val) == 0 {
return nil, fmt.Errorf("no stepDuration given")
}
meta.stepDuration = val
} else {
return nil, fmt.Errorf("no stepDuration given")
}
//verticalWindow
if val, ok := config.TriggerMetadata["verticalWindow"]; ok {
verticalWindow, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("verticalWindow parsing error %w", err)
}
meta.verticalWindow = verticalWindow
} else {
return nil, fmt.Errorf("no verticalWindow given")
}
//horizontalWindow
if val, ok := config.TriggerMetadata["horizontalWindow"]; ok {
horizontalWindow, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("horizontalWindow parsing error %w", err)
}
meta.horizontalWindow = horizontalWindow
} else {
return nil, fmt.Errorf("no horizontalWindow given")
}
//prometheusAddress
if val, ok := config.TriggerMetadata["prometheusAddress"]; ok {
err = validate.Var(val, "url")
if err != nil {
return nil, fmt.Errorf("invalid prometheusAddress")
}
meta.prometheusAddress = val
} else {
return nil, fmt.Errorf("no prometheusAddress given")
}
// predictionServiceAddress
if val, ok := config.TriggerMetadata["predictionServiceAddress"]; ok {
if len(val) == 0 {
return nil, fmt.Errorf("invalid predictionServiceAddress")
}
meta.predictionServiceAddress = val
} else {
return nil, fmt.Errorf("no predictionServiceAddress given")
}
//query
if val, ok := config.TriggerMetadata["query"]; ok {
if len(val) == 0 {
return nil, fmt.Errorf("no query given")
}
meta.query = val
} else {
return nil, fmt.Errorf("no query given")
}
//threshold
if val, ok := config.TriggerMetadata["threshold"]; ok {
threshold, err := strconv.ParseFloat(val, 64)
if err != nil {
return nil, fmt.Errorf("threshold parsing error %w", err)
}
meta.threshold = threshold
} else {
return nil, fmt.Errorf("no threshold given")
}
//activationThreshold
meta.activationThreshold = 0
if val, ok := config.TriggerMetadata["activationThreshold"]; ok {
activationThreshold, err := strconv.ParseFloat(val, 64)
if err != nil {
return nil, fmt.Errorf("activationThreshold parsing error %w", err)
}
meta.activationThreshold = activationThreshold
}
// scalerIndex
meta.scalerIndex = config.ScalerIndex
return &meta, nil
}
func (s *openPredictionScaler) Close(_ context.Context) error {
if s != nil && s.grpcConn != nil {
return s.grpcConn.Close()
}
return nil
}
func (s *openPredictionScaler) GetMetricSpecForScaling(context.Context) []v2.MetricSpec {
metricName := kedautil.NormalizeString(fmt.Sprintf("openPrediction-%s", openPredictionMetricPrefix))
externalMetric := &v2.ExternalMetricSource{
Metric: v2.MetricIdentifier{
Name: GenerateMetricNameWithIndex(s.metadata.scalerIndex, metricName),
},
Target: GetMetricTargetMili(s.metrictype, s.metadata.threshold),
}
metricSpec := v2.MetricSpec{
External: externalMetric, Type: openPredictionMetricType,
}
return []v2.MetricSpec{metricSpec}
}
func (s *openPredictionScaler) GetMetricsAndActivity(ctx context.Context, metricName string) ([]external_metrics.ExternalMetricValue, bool, error) {
value, activationValue, err := s.doPredictRequest(ctx)
if err != nil {
s.logger.Error(err, "error executing query to predict controller service")
return []external_metrics.ExternalMetricValue{}, false, err
}
if value == 0 {
s.logger.V(1).Info("empty response after predict request")
return []external_metrics.ExternalMetricValue{}, false, nil
}
s.logger.V(1).Info(fmt.Sprintf("predict value is: %f", value))
metric := GenerateMetricInMili(metricName, value)
return []external_metrics.ExternalMetricValue{metric}, activationValue > s.metadata.activationThreshold, nil
}
func (s *openPredictionScaler) doPredictRequest(ctx context.Context) (float64, float64, error) {
results, err := s.doQuery(ctx)
if err != nil {
return 0, 0, err
}
metricName := GenerateMetricNameWithIndex(s.metadata.scalerIndex, kedautil.NormalizeString(fmt.Sprintf("openPrediction-%s", openPredictionMetricPrefix)))
requestData := &prediction.PredictionRequest{
MicorserviceName: metricName,
Measurements: results,
History: s.metadata.history,
StepDuration: s.metadata.stepDuration,
PredictVerticalWindow: int32(s.metadata.verticalWindow),
PredictHorizontalWindow: int32(s.metadata.horizontalWindow),
}
resp, err := s.grpcClient.ProcessData(ctx, requestData)
if err != nil {
return 0, 0, err
}
var y float64
if len(results) > 0 {
y = results[len(results)-1]
}
x := float64(resp.Result)
return func(x, y float64) float64 {
if x < y {
return y
}
return x
}(x, y), y, nil
}
func (s *openPredictionScaler) doQuery(ctx context.Context) ([]float64, error) {
currentTime := time.Now().UTC()
if s.metadata.stepDuration == "" {
s.metadata.stepDuration = default_step
}
//parse string to Duration
history, err := str2duration.ParseDuration(s.metadata.history)
if err != nil {
return nil, fmt.Errorf("history parsing error %w", err)
}
stepDuration, err := str2duration.ParseDuration(s.metadata.stepDuration)
if err != nil {
return nil, fmt.Errorf("stepDuration parsing error %w", err)
}
r := v1.Range{
Start: currentTime.Add(-history),
End: currentTime,
Step: stepDuration,
}
val, warns, err := s.api.QueryRange(ctx, s.metadata.query, r)
if len(warns) > 0 {
s.logger.V(1).Info("warnings", warns)
}
if err != nil {
return nil, err
}
return s.parsePrometheusResult(val)
}
// parsePrometheusResult parsing response from prometheus server.
func (s *openPredictionScaler) parsePrometheusResult(result model.Value) (out []float64, err error) {
switch result.Type() {
case model.ValVector:
if res, ok := result.(model.Vector); ok {
for _, val := range res {
if err != nil {
return nil, err
}
out = append(out, float64(val.Value))
}
}
case model.ValMatrix:
if res, ok := result.(model.Matrix); ok {
for _, val := range res {
for _, v := range val.Values {
if err != nil {
return nil, err
}
out = append(out, float64(v.Value))
}
}
}
case model.ValScalar:
if res, ok := result.(*model.Scalar); ok {
if err != nil {
return nil, err
}
out = append(out, float64(res.Value))
}
case model.ValString:
if res, ok := result.(*model.String); ok {
if err != nil {
return nil, err
}
s, err := strconv.ParseFloat(res.Value, 64)
if err != nil {
return nil, err
}
out = append(out, s)
}
default:
return nil, err
}
return out, nil
}
// initOpenPredictionPrometheusConn init prometheus client and setup connection to API
func (s *openPredictionScaler) initOpenPredictionPrometheusConn(ctx context.Context) (err error) {
client, err := api.NewClient(api.Config{
Address: s.metadata.prometheusAddress,
})
if err != nil {
s.logger.V(1).Error(err, "init Prometheus client")
return err
}
s.prometheusClient = client
s.api = v1.NewAPI(s.prometheusClient)
return s.ping(ctx)
}
func (s *openPredictionScaler) ping(ctx context.Context) (err error) {
_, err = s.api.Runtimeinfo(ctx)
return err
}
/*
Copyright 2023 The KEDA Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package scaling
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
"github.com/kedacore/keda/v2/pkg/common/message"
"github.com/kedacore/keda/v2/pkg/eventreason"
"github.com/kedacore/keda/v2/pkg/scalers"
"github.com/kedacore/keda/v2/pkg/scaling/cache"
"github.com/kedacore/keda/v2/pkg/scaling/resolver"
)
/// --------------------------------------------------------------------------- ///
/// ---------- Scaler-Building related methods --------- ///
/// --------------------------------------------------------------------------- ///
// buildScalers returns list of Scalers for the specified triggers
func (h *scaleHandler) buildScalers(ctx context.Context, withTriggers *kedav1alpha1.WithTriggers, podTemplateSpec *corev1.PodTemplateSpec, containerName string) ([]cache.ScalerBuilder, error) {
logger := log.WithValues("type", withTriggers.Kind, "namespace", withTriggers.Namespace, "name", withTriggers.Name)
var err error
resolvedEnv := make(map[string]string)
result := make([]cache.ScalerBuilder, 0, len(withTriggers.Spec.Triggers))
for i, t := range withTriggers.Spec.Triggers {
triggerIndex, trigger := i, t
factory := func() (scalers.Scaler, *scalers.ScalerConfig, error) {
if podTemplateSpec != nil {
resolvedEnv, err = resolver.ResolveContainerEnv(ctx, h.client, logger, &podTemplateSpec.Spec, containerName, withTriggers.Namespace, h.secretsLister)
if err != nil {
return nil, nil, fmt.Errorf("error resolving secrets for ScaleTarget: %w", err)
}
}
config := &scalers.ScalerConfig{
ScalableObjectName: withTriggers.Name,
ScalableObjectNamespace: withTriggers.Namespace,
ScalableObjectType: withTriggers.Kind,
TriggerName: trigger.Name,
TriggerMetadata: trigger.Metadata,
TriggerUseCachedMetrics: trigger.UseCachedMetrics,
ResolvedEnv: resolvedEnv,
AuthParams: make(map[string]string),
GlobalHTTPTimeout: h.globalHTTPTimeout,
ScalerIndex: triggerIndex,
MetricType: trigger.MetricType,
}
authParams, podIdentity, err := resolver.ResolveAuthRefAndPodIdentity(ctx, h.client, logger, trigger.AuthenticationRef, podTemplateSpec, withTriggers.Namespace, h.secretsLister)
if err != nil {
return nil, nil, err
}
config.AuthParams = authParams
config.PodIdentity = podIdentity
scaler, err := buildScaler(ctx, h.client, trigger.Type, config)
return scaler, config, err
}
scaler, config, err := factory()
if err != nil {
h.recorder.Event(withTriggers, corev1.EventTypeWarning, eventreason.KEDAScalerFailed, err.Error())
logger.Error(err, "error resolving auth params", "scalerIndex", triggerIndex)
if scaler != nil {
scaler.Close(ctx)
}
for _, builder := range result {
builder.Scaler.Close(ctx)
}
return nil, err
}
msg := fmt.Sprintf(message.ScalerIsBuiltMsg, trigger.Type)
h.recorder.Event(withTriggers, corev1.EventTypeNormal, eventreason.KEDAScalersStarted, msg)
result = append(result, cache.ScalerBuilder{
Scaler: scaler,
ScalerConfig: *config,
Factory: factory,
})
}
return result, nil
}
// buildScaler builds a scaler form input config and trigger type
func buildScaler(ctx context.Context, client client.Client, triggerType string, config *scalers.ScalerConfig) (scalers.Scaler, error) {
// TRIGGERS-START
switch triggerType {
case "activemq":
return scalers.NewActiveMQScaler(config)
case "arangodb":
return scalers.NewArangoDBScaler(config)
case "artemis-queue":
return scalers.NewArtemisQueueScaler(config)
case "aws-cloudwatch":
return scalers.NewAwsCloudwatchScaler(ctx, config)
case "aws-dynamodb":
return scalers.NewAwsDynamoDBScaler(ctx, config)
case "aws-dynamodb-streams":
return scalers.NewAwsDynamoDBStreamsScaler(ctx, config)
case "aws-kinesis-stream":
return scalers.NewAwsKinesisStreamScaler(ctx, config)
case "aws-sqs-queue":
return scalers.NewAwsSqsQueueScaler(ctx, config)
case "azure-app-insights":
return scalers.NewAzureAppInsightsScaler(config)
case "azure-blob":
return scalers.NewAzureBlobScaler(config)
case "azure-data-explorer":
return scalers.NewAzureDataExplorerScaler(config)
case "azure-eventhub":
return scalers.NewAzureEventHubScaler(ctx, config)
case "azure-log-analytics":
return scalers.NewAzureLogAnalyticsScaler(config)
case "azure-monitor":
return scalers.NewAzureMonitorScaler(config)
case "azure-pipelines":
return scalers.NewAzurePipelinesScaler(ctx, config)
case "azure-queue":
return scalers.NewAzureQueueScaler(config)
case "azure-servicebus":
return scalers.NewAzureServiceBusScaler(ctx, config)
case "cassandra":
return scalers.NewCassandraScaler(config)
case "couchdb":
return scalers.NewCouchDBScaler(ctx, config)
case "cpu":
return scalers.NewCPUMemoryScaler(corev1.ResourceCPU, config)
case "cron":
return scalers.NewCronScaler(config)
case "datadog":
return scalers.NewDatadogScaler(ctx, config)
case "elasticsearch":
return scalers.NewElasticsearchScaler(config)
case "etcd":
return scalers.NewEtcdScaler(config)
case "external":
return scalers.NewExternalScaler(config)
// TODO: use other way for test.
case "external-mock":
return scalers.NewExternalMockScaler(config)
case "external-push":
return scalers.NewExternalPushScaler(config)
case "gcp-cloudtasks":
return scalers.NewGcpCloudTasksScaler(config)
case "gcp-pubsub":
return scalers.NewPubSubScaler(config)
case "gcp-stackdriver":
return scalers.NewStackdriverScaler(ctx, config)
case "gcp-storage":
return scalers.NewGcsScaler(config)
case "github-runner":
return scalers.NewGitHubRunnerScaler(config)
case "graphite":
return scalers.NewGraphiteScaler(config)
case "huawei-cloudeye":
return scalers.NewHuaweiCloudeyeScaler(config)
case "ibmmq":
return scalers.NewIBMMQScaler(config)
case "influxdb":
return scalers.NewInfluxDBScaler(config)
case "kafka":
return scalers.NewKafkaScaler(config)
case "kubernetes-workload":
return scalers.NewKubernetesWorkloadScaler(client, config)
case "liiklus":
return scalers.NewLiiklusScaler(config)
case "loki":
return scalers.NewLokiScaler(config)
case "memory":
return scalers.NewCPUMemoryScaler(corev1.ResourceMemory, config)
case "metrics-api":
return scalers.NewMetricsAPIScaler(config)
case "mongodb":
return scalers.NewMongoDBScaler(ctx, config)
case "mssql":
return scalers.NewMSSQLScaler(config)
case "mysql":
return scalers.NewMySQLScaler(config)
case "nats-jetstream":
return scalers.NewNATSJetStreamScaler(config)
case "new-relic":
return scalers.NewNewRelicScaler(config)
//Edit by Mhdbashar
case "open-prediction":
return scalers.NewopenPredictionScaler(ctx, config)
case "openstack-metric":
return scalers.NewOpenstackMetricScaler(ctx, config)
case "openstack-swift":
return scalers.NewOpenstackSwiftScaler(ctx, config)
case "postgresql":
return scalers.NewPostgreSQLScaler(config)
case "predictkube":
return scalers.NewPredictKubeScaler(ctx, config)
case "prometheus":
return scalers.NewPrometheusScaler(config)
case "pulsar":
return scalers.NewPulsarScaler(config)
case "rabbitmq":
return scalers.NewRabbitMQScaler(config)
case "redis":
return scalers.NewRedisScaler(ctx, false, false, config)
case "redis-cluster":
return scalers.NewRedisScaler(ctx, true, false, config)
case "redis-cluster-streams":
return scalers.NewRedisStreamsScaler(ctx, true, false, config)
case "redis-sentinel":
return scalers.NewRedisScaler(ctx, false, true, config)
case "redis-sentinel-streams":
return scalers.NewRedisStreamsScaler(ctx, false, true, config)
case "redis-streams":
return scalers.NewRedisStreamsScaler(ctx, false, false, config)
case "selenium-grid":
return scalers.NewSeleniumGridScaler(config)
case "solace-event-queue":
return scalers.NewSolaceScaler(config)
case "solr":
return scalers.NewSolrScaler(config)
case "stan":
return scalers.NewStanScaler(config)
default:
return nil, fmt.Errorf("no scaler found for type: %s", triggerType)
}
// TRIGGERS-END
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: prediction.proto
package prediction
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type PredictionRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MicorserviceName string `protobuf:"bytes,1,opt,name=micorservice_name,json=micorserviceName,proto3" json:"micorservice_name,omitempty"`
Measurements []float64 `protobuf:"fixed64,2,rep,packed,name=measurements,proto3" json:"measurements,omitempty"`
History string `protobuf:"bytes,3,opt,name=history,proto3" json:"history,omitempty"`
StepDuration string `protobuf:"bytes,4,opt,name=stepDuration,proto3" json:"stepDuration,omitempty"`
PredictVerticalWindow int32 `protobuf:"varint,5,opt,name=predictVerticalWindow,proto3" json:"predictVerticalWindow,omitempty"`
PredictHorizontalWindow int32 `protobuf:"varint,6,opt,name=predictHorizontalWindow,proto3" json:"predictHorizontalWindow,omitempty"`
}
func (x *PredictionRequest) Reset() {
*x = PredictionRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_prediction_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PredictionRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PredictionRequest) ProtoMessage() {}
func (x *PredictionRequest) ProtoReflect() protoreflect.Message {
mi := &file_prediction_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PredictionRequest.ProtoReflect.Descriptor instead.
func (*PredictionRequest) Descriptor() ([]byte, []int) {
return file_prediction_proto_rawDescGZIP(), []int{0}
}
func (x *PredictionRequest) GetMicorserviceName() string {
if x != nil {
return x.MicorserviceName
}
return ""
}
func (x *PredictionRequest) GetMeasurements() []float64 {
if x != nil {
return x.Measurements
}
return nil
}
func (x *PredictionRequest) GetHistory() string {
if x != nil {
return x.History
}
return ""
}
func (x *PredictionRequest) GetStepDuration() string {
if x != nil {
return x.StepDuration
}
return ""
}
func (x *PredictionRequest) GetPredictVerticalWindow() int32 {
if x != nil {
return x.PredictVerticalWindow
}
return 0
}
func (x *PredictionRequest) GetPredictHorizontalWindow() int32 {
if x != nil {
return x.PredictHorizontalWindow
}
return 0
}
type PredictionResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Result int32 `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"`
}
func (x *PredictionResponse) Reset() {
*x = PredictionResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_prediction_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PredictionResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PredictionResponse) ProtoMessage() {}
func (x *PredictionResponse) ProtoReflect() protoreflect.Message {
mi := &file_prediction_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PredictionResponse.ProtoReflect.Descriptor instead.
func (*PredictionResponse) Descriptor() ([]byte, []int) {
return file_prediction_proto_rawDescGZIP(), []int{1}
}
func (x *PredictionResponse) GetResult() int32 {
if x != nil {
return x.Result
}
return 0
}
var File_prediction_proto protoreflect.FileDescriptor
var file_prediction_proto_rawDesc = []byte{
0x0a, 0x10, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x0a, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x92,
0x02, 0x0a, 0x11, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x69, 0x63, 0x6f, 0x72, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x10, 0x6d, 0x69, 0x63, 0x6f, 0x72, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12,
0x22, 0x0a, 0x0c, 0x73, 0x74, 0x65, 0x70, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x74, 0x65, 0x70, 0x44, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x15, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x56, 0x65,
0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01,
0x28, 0x05, 0x52, 0x15, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x56, 0x65, 0x72, 0x74, 0x69,
0x63, 0x61, 0x6c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x38, 0x0a, 0x17, 0x70, 0x72, 0x65,
0x64, 0x69, 0x63, 0x74, 0x48, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x57, 0x69,
0x6e, 0x64, 0x6f, 0x77, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x70, 0x72, 0x65, 0x64,
0x69, 0x63, 0x74, 0x48, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x57, 0x69, 0x6e,
0x64, 0x6f, 0x77, 0x22, 0x2c, 0x0a, 0x12, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x32, 0x61, 0x0a, 0x11, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
0x73, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_prediction_proto_rawDescOnce sync.Once
file_prediction_proto_rawDescData = file_prediction_proto_rawDesc
)
func file_prediction_proto_rawDescGZIP() []byte {
file_prediction_proto_rawDescOnce.Do(func() {
file_prediction_proto_rawDescData = protoimpl.X.CompressGZIP(file_prediction_proto_rawDescData)
})
return file_prediction_proto_rawDescData
}
var file_prediction_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_prediction_proto_goTypes = []interface{}{
(*PredictionRequest)(nil), // 0: prediction.PredictionRequest
(*PredictionResponse)(nil), // 1: prediction.PredictionResponse
}
var file_prediction_proto_depIdxs = []int32{
0, // 0: prediction.PredictionService.ProcessData:input_type -> prediction.PredictionRequest
1, // 1: prediction.PredictionService.ProcessData:output_type -> prediction.PredictionResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_prediction_proto_init() }
func file_prediction_proto_init() {
if File_prediction_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_prediction_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PredictionRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_prediction_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PredictionResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_prediction_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_prediction_proto_goTypes,
DependencyIndexes: file_prediction_proto_depIdxs,
MessageInfos: file_prediction_proto_msgTypes,
}.Build()
File_prediction_proto = out.File
file_prediction_proto_rawDesc = nil
file_prediction_proto_goTypes = nil
file_prediction_proto_depIdxs = nil
}
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc (unknown)
// source: prediction.proto
package prediction
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// PredictionServiceClient is the client API for PredictionService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PredictionServiceClient interface {
ProcessData(ctx context.Context, in *PredictionRequest, opts ...grpc.CallOption) (*PredictionResponse, error)
}
type predictionServiceClient struct {
cc grpc.ClientConnInterface
}
func NewPredictionServiceClient(cc grpc.ClientConnInterface) PredictionServiceClient {
return &predictionServiceClient{cc}
}
func (c *predictionServiceClient) ProcessData(ctx context.Context, in *PredictionRequest, opts ...grpc.CallOption) (*PredictionResponse, error) {
out := new(PredictionResponse)
err := c.cc.Invoke(ctx, "/prediction.PredictionService/ProcessData", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// PredictionServiceServer is the server API for PredictionService service.
// All implementations must embed UnimplementedPredictionServiceServer
// for forward compatibility
type PredictionServiceServer interface {
ProcessData(context.Context, *PredictionRequest) (*PredictionResponse, error)
mustEmbedUnimplementedPredictionServiceServer()
}
// UnimplementedPredictionServiceServer must be embedded to have forward compatible implementations.
type UnimplementedPredictionServiceServer struct {
}
func (UnimplementedPredictionServiceServer) ProcessData(context.Context, *PredictionRequest) (*PredictionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ProcessData not implemented")
}
func (UnimplementedPredictionServiceServer) mustEmbedUnimplementedPredictionServiceServer() {}
// UnsafePredictionServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PredictionServiceServer will
// result in compilation errors.
type UnsafePredictionServiceServer interface {
mustEmbedUnimplementedPredictionServiceServer()
}
func RegisterPredictionServiceServer(s grpc.ServiceRegistrar, srv PredictionServiceServer) {
s.RegisterService(&PredictionService_ServiceDesc, srv)
}
func _PredictionService_ProcessData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PredictionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PredictionServiceServer).ProcessData(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/prediction.PredictionService/ProcessData",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PredictionServiceServer).ProcessData(ctx, req.(*PredictionRequest))
}
return interceptor(ctx, in, info, handler)
}
// PredictionService_ServiceDesc is the grpc.ServiceDesc for PredictionService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PredictionService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "prediction.PredictionService",
HandlerType: (*PredictionServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ProcessData",
Handler: _PredictionService_ProcessData_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "prediction.proto",
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment