github.com/weaviate/weaviate@v1.24.6/adapters/handlers/grpc/v1/service.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package v1 13 14 import ( 15 "context" 16 "fmt" 17 "time" 18 19 "github.com/sirupsen/logrus" 20 enterrors "github.com/weaviate/weaviate/entities/errors" 21 22 "github.com/weaviate/weaviate/usecases/config" 23 24 "github.com/weaviate/weaviate/usecases/objects" 25 26 "github.com/weaviate/weaviate/entities/additional" 27 "github.com/weaviate/weaviate/entities/dto" 28 "github.com/weaviate/weaviate/entities/schema" 29 pb "github.com/weaviate/weaviate/grpc/generated/protocol/v1" 30 "github.com/weaviate/weaviate/usecases/auth/authentication/composer" 31 schemaManager "github.com/weaviate/weaviate/usecases/schema" 32 "github.com/weaviate/weaviate/usecases/traverser" 33 ) 34 35 type Service struct { 36 pb.UnimplementedWeaviateServer 37 traverser *traverser.Traverser 38 authComposer composer.TokenFunc 39 allowAnonymousAccess bool 40 schemaManager *schemaManager.Manager 41 batchManager *objects.BatchManager 42 config *config.Config 43 logger logrus.FieldLogger 44 } 45 46 func NewService(traverser *traverser.Traverser, authComposer composer.TokenFunc, 47 allowAnonymousAccess bool, schemaManager *schemaManager.Manager, 48 batchManager *objects.BatchManager, config *config.Config, logger logrus.FieldLogger, 49 ) *Service { 50 return &Service{ 51 traverser: traverser, 52 authComposer: authComposer, 53 allowAnonymousAccess: allowAnonymousAccess, 54 schemaManager: schemaManager, 55 batchManager: batchManager, 56 config: config, 57 logger: logger, 58 } 59 } 60 61 func (s *Service) BatchDelete(ctx context.Context, req *pb.BatchDeleteRequest) (*pb.BatchDeleteReply, error) { 62 before := time.Now() 63 principal, err := s.principalFromContext(ctx) 64 if err != nil { 65 return nil, fmt.Errorf("extract auth: %w", err) 66 } 67 replicationProperties := extractReplicationProperties(req.ConsistencyLevel) 68 scheme := s.schemaManager.GetSchemaSkipAuth() 69 70 params, err := batchDeleteParamsFromProto(req, scheme) 71 if err != nil { 72 return nil, fmt.Errorf("batch delete params: %w", err) 73 } 74 75 tenant := "" 76 if req.Tenant != nil { 77 tenant = *req.Tenant 78 } 79 80 response, err := s.batchManager.DeleteObjectsFromGRPC(ctx, principal, params, replicationProperties, tenant) 81 if err != nil { 82 return nil, fmt.Errorf("batch delete: %w", err) 83 } 84 85 result, err := batchDeleteReplyFromObjects(response, req.Verbose) 86 if err != nil { 87 return nil, fmt.Errorf("batch delete reply: %w", err) 88 } 89 result.Took = float32(time.Since(before).Seconds()) 90 91 return result, nil 92 } 93 94 func (s *Service) BatchObjects(ctx context.Context, req *pb.BatchObjectsRequest) (*pb.BatchObjectsReply, error) { 95 before := time.Now() 96 principal, err := s.principalFromContext(ctx) 97 if err != nil { 98 return nil, fmt.Errorf("extract auth: %w", err) 99 } 100 scheme := s.schemaManager.GetSchemaSkipAuth() 101 102 objs, objOriginalIndex, objectParsingErrors := batchFromProto(req, scheme) 103 104 replicationProperties := extractReplicationProperties(req.ConsistencyLevel) 105 106 all := "ALL" 107 response, err := s.batchManager.AddObjects(ctx, principal, objs, []*string{&all}, replicationProperties) 108 if err != nil { 109 return nil, err 110 } 111 var objErrors []*pb.BatchObjectsReply_BatchError 112 113 for i, obj := range response { 114 if obj.Err != nil { 115 objErrors = append(objErrors, &pb.BatchObjectsReply_BatchError{Index: int32(objOriginalIndex[i]), Error: obj.Err.Error()}) 116 } 117 } 118 119 for i, err := range objectParsingErrors { 120 objErrors = append(objErrors, &pb.BatchObjectsReply_BatchError{Index: int32(i), Error: err.Error()}) 121 } 122 123 result := &pb.BatchObjectsReply{ 124 Took: float32(time.Since(before).Seconds()), 125 Errors: objErrors, 126 } 127 return result, nil 128 } 129 130 func (s *Service) Search(ctx context.Context, req *pb.SearchRequest) (*pb.SearchReply, error) { 131 before := time.Now() 132 133 principal, err := s.principalFromContext(ctx) 134 if err != nil { 135 return nil, fmt.Errorf("extract auth: %w", err) 136 } 137 138 scheme := s.schemaManager.GetSchemaSkipAuth() 139 140 type reply struct { 141 Result *pb.SearchReply 142 Error error 143 } 144 145 c := make(chan reply, 1) 146 f := func() { 147 defer func() { 148 if err := recover(); err != nil { 149 c <- reply{ 150 Result: nil, 151 Error: fmt.Errorf("panic occurred: %v", err), 152 } 153 } 154 }() 155 156 searchParams, err := searchParamsFromProto(req, scheme, s.config) 157 if err != nil { 158 c <- reply{ 159 Result: nil, 160 Error: fmt.Errorf("extract params: %w", err), 161 } 162 } 163 164 if err := s.validateClassAndProperty(searchParams); err != nil { 165 c <- reply{ 166 Result: nil, 167 Error: err, 168 } 169 } 170 171 res, err := s.traverser.GetClass(ctx, principal, searchParams) 172 if err != nil { 173 c <- reply{ 174 Result: nil, 175 Error: err, 176 } 177 } 178 179 proto, err := searchResultsToProto(res, before, searchParams, scheme, req.Uses_123Api) 180 c <- reply{ 181 Result: proto, 182 Error: err, 183 } 184 } 185 enterrors.GoWrapper(f, s.logger) 186 res := <-c 187 return res.Result, res.Error 188 } 189 190 func (s *Service) validateClassAndProperty(searchParams dto.GetParams) error { 191 scheme := s.schemaManager.GetSchemaSkipAuth() 192 class, err := schema.GetClassByName(scheme.Objects, searchParams.ClassName) 193 if err != nil { 194 return err 195 } 196 197 for _, prop := range searchParams.Properties { 198 _, err := schema.GetPropertyByName(class, prop.Name) 199 if err != nil { 200 return err 201 } 202 } 203 204 return nil 205 } 206 207 func extractReplicationProperties(level *pb.ConsistencyLevel) *additional.ReplicationProperties { 208 if level == nil { 209 return nil 210 } 211 212 switch *level { 213 case pb.ConsistencyLevel_CONSISTENCY_LEVEL_ONE: 214 return &additional.ReplicationProperties{ConsistencyLevel: "ONE"} 215 case pb.ConsistencyLevel_CONSISTENCY_LEVEL_QUORUM: 216 return &additional.ReplicationProperties{ConsistencyLevel: "QUORUM"} 217 case pb.ConsistencyLevel_CONSISTENCY_LEVEL_ALL: 218 return &additional.ReplicationProperties{ConsistencyLevel: "ALL"} 219 default: 220 return nil 221 } 222 }