1// Copyright 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Code generated by gapic-generator. DO NOT EDIT. 16 17package vision 18 19import ( 20 "context" 21 "fmt" 22 "math" 23 "time" 24 25 "cloud.google.com/go/longrunning" 26 lroauto "cloud.google.com/go/longrunning/autogen" 27 "github.com/golang/protobuf/proto" 28 gax "github.com/googleapis/gax-go/v2" 29 "google.golang.org/api/iterator" 30 "google.golang.org/api/option" 31 "google.golang.org/api/transport" 32 visionpb "google.golang.org/genproto/googleapis/cloud/vision/v1" 33 longrunningpb "google.golang.org/genproto/googleapis/longrunning" 34 "google.golang.org/grpc" 35 "google.golang.org/grpc/codes" 36 "google.golang.org/grpc/metadata" 37) 38 39// ProductSearchCallOptions contains the retry settings for each method of ProductSearchClient. 40type ProductSearchCallOptions struct { 41 CreateProduct []gax.CallOption 42 ListProducts []gax.CallOption 43 GetProduct []gax.CallOption 44 UpdateProduct []gax.CallOption 45 DeleteProduct []gax.CallOption 46 ListReferenceImages []gax.CallOption 47 GetReferenceImage []gax.CallOption 48 DeleteReferenceImage []gax.CallOption 49 CreateReferenceImage []gax.CallOption 50 CreateProductSet []gax.CallOption 51 ListProductSets []gax.CallOption 52 GetProductSet []gax.CallOption 53 UpdateProductSet []gax.CallOption 54 DeleteProductSet []gax.CallOption 55 AddProductToProductSet []gax.CallOption 56 RemoveProductFromProductSet []gax.CallOption 57 ListProductsInProductSet []gax.CallOption 58 ImportProductSets []gax.CallOption 59} 60 61func defaultProductSearchClientOptions() []option.ClientOption { 62 return []option.ClientOption{ 63 option.WithEndpoint("vision.googleapis.com:443"), 64 option.WithScopes(DefaultAuthScopes()...), 65 } 66} 67 68func defaultProductSearchCallOptions() *ProductSearchCallOptions { 69 retry := map[[2]string][]gax.CallOption{ 70 {"default", "idempotent"}: { 71 gax.WithRetry(func() gax.Retryer { 72 return gax.OnCodes([]codes.Code{ 73 codes.DeadlineExceeded, 74 codes.Unavailable, 75 }, gax.Backoff{ 76 Initial: 100 * time.Millisecond, 77 Max: 60000 * time.Millisecond, 78 Multiplier: 1.3, 79 }) 80 }), 81 }, 82 } 83 return &ProductSearchCallOptions{ 84 CreateProduct: retry[[2]string{"default", "non_idempotent"}], 85 ListProducts: retry[[2]string{"default", "idempotent"}], 86 GetProduct: retry[[2]string{"default", "idempotent"}], 87 UpdateProduct: retry[[2]string{"default", "idempotent"}], 88 DeleteProduct: retry[[2]string{"default", "idempotent"}], 89 ListReferenceImages: retry[[2]string{"default", "idempotent"}], 90 GetReferenceImage: retry[[2]string{"default", "idempotent"}], 91 DeleteReferenceImage: retry[[2]string{"default", "idempotent"}], 92 CreateReferenceImage: retry[[2]string{"default", "non_idempotent"}], 93 CreateProductSet: retry[[2]string{"default", "non_idempotent"}], 94 ListProductSets: retry[[2]string{"default", "idempotent"}], 95 GetProductSet: retry[[2]string{"default", "idempotent"}], 96 UpdateProductSet: retry[[2]string{"default", "idempotent"}], 97 DeleteProductSet: retry[[2]string{"default", "idempotent"}], 98 AddProductToProductSet: retry[[2]string{"default", "idempotent"}], 99 RemoveProductFromProductSet: retry[[2]string{"default", "idempotent"}], 100 ListProductsInProductSet: retry[[2]string{"default", "idempotent"}], 101 ImportProductSets: retry[[2]string{"default", "non_idempotent"}], 102 } 103} 104 105// ProductSearchClient is a client for interacting with Cloud Vision API. 106// 107// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls. 108type ProductSearchClient struct { 109 // The connection to the service. 110 conn *grpc.ClientConn 111 112 // The gRPC API client. 113 productSearchClient visionpb.ProductSearchClient 114 115 // LROClient is used internally to handle longrunning operations. 116 // It is exposed so that its CallOptions can be modified if required. 117 // Users should not Close this client. 118 LROClient *lroauto.OperationsClient 119 120 // The call options for this service. 121 CallOptions *ProductSearchCallOptions 122 123 // The x-goog-* metadata to be sent with each request. 124 xGoogMetadata metadata.MD 125} 126 127// NewProductSearchClient creates a new product search client. 128// 129// Manages Products and ProductSets of reference images for use in product 130// search. It uses the following resource model: 131// 132// The API has a collection of [ProductSet][google.cloud.vision.v1.ProductSet] 133// resources, named projects/*/locations/*/productSets/*, which acts as a way 134// to put different products into groups to limit identification. 135// 136// In parallel, 137// 138// The API has a collection of [Product][google.cloud.vision.v1.Product] 139// resources, named 140// projects/*/locations/*/products/* 141// 142// Each [Product][google.cloud.vision.v1.Product] has a collection of 143// [ReferenceImage][google.cloud.vision.v1.ReferenceImage] resources, named 144// projects/*/locations/*/products/*/referenceImages/* 145func NewProductSearchClient(ctx context.Context, opts ...option.ClientOption) (*ProductSearchClient, error) { 146 conn, err := transport.DialGRPC(ctx, append(defaultProductSearchClientOptions(), opts...)...) 147 if err != nil { 148 return nil, err 149 } 150 c := &ProductSearchClient{ 151 conn: conn, 152 CallOptions: defaultProductSearchCallOptions(), 153 154 productSearchClient: visionpb.NewProductSearchClient(conn), 155 } 156 c.setGoogleClientInfo() 157 158 c.LROClient, err = lroauto.NewOperationsClient(ctx, option.WithGRPCConn(conn)) 159 if err != nil { 160 // This error "should not happen", since we are just reusing old connection 161 // and never actually need to dial. 162 // If this does happen, we could leak conn. However, we cannot close conn: 163 // If the user invoked the function with option.WithGRPCConn, 164 // we would close a connection that's still in use. 165 // TODO(pongad): investigate error conditions. 166 return nil, err 167 } 168 return c, nil 169} 170 171// Connection returns the client's connection to the API service. 172func (c *ProductSearchClient) Connection() *grpc.ClientConn { 173 return c.conn 174} 175 176// Close closes the connection to the API service. The user should invoke this when 177// the client is no longer required. 178func (c *ProductSearchClient) Close() error { 179 return c.conn.Close() 180} 181 182// setGoogleClientInfo sets the name and version of the application in 183// the `x-goog-api-client` header passed on each request. Intended for 184// use by Google-written clients. 185func (c *ProductSearchClient) setGoogleClientInfo(keyval ...string) { 186 kv := append([]string{"gl-go", versionGo()}, keyval...) 187 kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version) 188 c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...)) 189} 190 191// CreateProduct creates and returns a new product resource. 192// 193// Possible errors: 194// 195// Returns INVALID_ARGUMENT if display_name is missing or longer than 4096 196// characters. 197// 198// Returns INVALID_ARGUMENT if description is longer than 4096 characters. 199// 200// Returns INVALID_ARGUMENT if product_category is missing or invalid. 201func (c *ProductSearchClient) CreateProduct(ctx context.Context, req *visionpb.CreateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 202 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 203 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 204 opts = append(c.CallOptions.CreateProduct[0:len(c.CallOptions.CreateProduct):len(c.CallOptions.CreateProduct)], opts...) 205 var resp *visionpb.Product 206 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 207 var err error 208 resp, err = c.productSearchClient.CreateProduct(ctx, req, settings.GRPC...) 209 return err 210 }, opts...) 211 if err != nil { 212 return nil, err 213 } 214 return resp, nil 215} 216 217// ListProducts lists products in an unspecified order. 218// 219// Possible errors: 220// 221// Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1. 222func (c *ProductSearchClient) ListProducts(ctx context.Context, req *visionpb.ListProductsRequest, opts ...gax.CallOption) *ProductIterator { 223 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 224 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 225 opts = append(c.CallOptions.ListProducts[0:len(c.CallOptions.ListProducts):len(c.CallOptions.ListProducts)], opts...) 226 it := &ProductIterator{} 227 req = proto.Clone(req).(*visionpb.ListProductsRequest) 228 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) { 229 var resp *visionpb.ListProductsResponse 230 req.PageToken = pageToken 231 if pageSize > math.MaxInt32 { 232 req.PageSize = math.MaxInt32 233 } else { 234 req.PageSize = int32(pageSize) 235 } 236 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 237 var err error 238 resp, err = c.productSearchClient.ListProducts(ctx, req, settings.GRPC...) 239 return err 240 }, opts...) 241 if err != nil { 242 return nil, "", err 243 } 244 return resp.Products, resp.NextPageToken, nil 245 } 246 fetch := func(pageSize int, pageToken string) (string, error) { 247 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 248 if err != nil { 249 return "", err 250 } 251 it.items = append(it.items, items...) 252 return nextPageToken, nil 253 } 254 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 255 it.pageInfo.MaxSize = int(req.PageSize) 256 return it 257} 258 259// GetProduct gets information associated with a Product. 260// 261// Possible errors: 262// 263// Returns NOT_FOUND if the Product does not exist. 264func (c *ProductSearchClient) GetProduct(ctx context.Context, req *visionpb.GetProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 265 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 266 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 267 opts = append(c.CallOptions.GetProduct[0:len(c.CallOptions.GetProduct):len(c.CallOptions.GetProduct)], opts...) 268 var resp *visionpb.Product 269 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 270 var err error 271 resp, err = c.productSearchClient.GetProduct(ctx, req, settings.GRPC...) 272 return err 273 }, opts...) 274 if err != nil { 275 return nil, err 276 } 277 return resp, nil 278} 279 280// UpdateProduct makes changes to a Product resource. 281// Only the display_name, description, and labels fields can be updated 282// right now. 283// 284// If labels are updated, the change will not be reflected in queries until 285// the next index time. 286// 287// Possible errors: 288// 289// Returns NOT_FOUND if the Product does not exist. 290// 291// Returns INVALID_ARGUMENT if display_name is present in update_mask but is 292// missing from the request or longer than 4096 characters. 293// 294// Returns INVALID_ARGUMENT if description is present in update_mask but is 295// longer than 4096 characters. 296// 297// Returns INVALID_ARGUMENT if product_category is present in update_mask. 298func (c *ProductSearchClient) UpdateProduct(ctx context.Context, req *visionpb.UpdateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 299 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product.name", req.GetProduct().GetName())) 300 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 301 opts = append(c.CallOptions.UpdateProduct[0:len(c.CallOptions.UpdateProduct):len(c.CallOptions.UpdateProduct)], opts...) 302 var resp *visionpb.Product 303 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 304 var err error 305 resp, err = c.productSearchClient.UpdateProduct(ctx, req, settings.GRPC...) 306 return err 307 }, opts...) 308 if err != nil { 309 return nil, err 310 } 311 return resp, nil 312} 313 314// DeleteProduct permanently deletes a product and its reference images. 315// 316// Metadata of the product and all its images will be deleted right away, but 317// search queries against ProductSets containing the product may still work 318// until all related caches are refreshed. 319// 320// Possible errors: 321// 322// Returns NOT_FOUND if the product does not exist. 323func (c *ProductSearchClient) DeleteProduct(ctx context.Context, req *visionpb.DeleteProductRequest, opts ...gax.CallOption) error { 324 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 325 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 326 opts = append(c.CallOptions.DeleteProduct[0:len(c.CallOptions.DeleteProduct):len(c.CallOptions.DeleteProduct)], opts...) 327 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 328 var err error 329 _, err = c.productSearchClient.DeleteProduct(ctx, req, settings.GRPC...) 330 return err 331 }, opts...) 332 return err 333} 334 335// ListReferenceImages lists reference images. 336// 337// Possible errors: 338// 339// Returns NOT_FOUND if the parent product does not exist. 340// 341// Returns INVALID_ARGUMENT if the page_size is greater than 100, or less 342// than 1. 343func (c *ProductSearchClient) ListReferenceImages(ctx context.Context, req *visionpb.ListReferenceImagesRequest, opts ...gax.CallOption) *ReferenceImageIterator { 344 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 345 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 346 opts = append(c.CallOptions.ListReferenceImages[0:len(c.CallOptions.ListReferenceImages):len(c.CallOptions.ListReferenceImages)], opts...) 347 it := &ReferenceImageIterator{} 348 req = proto.Clone(req).(*visionpb.ListReferenceImagesRequest) 349 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ReferenceImage, string, error) { 350 var resp *visionpb.ListReferenceImagesResponse 351 req.PageToken = pageToken 352 if pageSize > math.MaxInt32 { 353 req.PageSize = math.MaxInt32 354 } else { 355 req.PageSize = int32(pageSize) 356 } 357 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 358 var err error 359 resp, err = c.productSearchClient.ListReferenceImages(ctx, req, settings.GRPC...) 360 return err 361 }, opts...) 362 if err != nil { 363 return nil, "", err 364 } 365 return resp.ReferenceImages, resp.NextPageToken, nil 366 } 367 fetch := func(pageSize int, pageToken string) (string, error) { 368 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 369 if err != nil { 370 return "", err 371 } 372 it.items = append(it.items, items...) 373 return nextPageToken, nil 374 } 375 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 376 it.pageInfo.MaxSize = int(req.PageSize) 377 return it 378} 379 380// GetReferenceImage gets information associated with a ReferenceImage. 381// 382// Possible errors: 383// 384// Returns NOT_FOUND if the specified image does not exist. 385func (c *ProductSearchClient) GetReferenceImage(ctx context.Context, req *visionpb.GetReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) { 386 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 387 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 388 opts = append(c.CallOptions.GetReferenceImage[0:len(c.CallOptions.GetReferenceImage):len(c.CallOptions.GetReferenceImage)], opts...) 389 var resp *visionpb.ReferenceImage 390 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 391 var err error 392 resp, err = c.productSearchClient.GetReferenceImage(ctx, req, settings.GRPC...) 393 return err 394 }, opts...) 395 if err != nil { 396 return nil, err 397 } 398 return resp, nil 399} 400 401// DeleteReferenceImage permanently deletes a reference image. 402// 403// The image metadata will be deleted right away, but search queries 404// against ProductSets containing the image may still work until all related 405// caches are refreshed. 406// 407// The actual image files are not deleted from Google Cloud Storage. 408// 409// Possible errors: 410// 411// Returns NOT_FOUND if the reference image does not exist. 412func (c *ProductSearchClient) DeleteReferenceImage(ctx context.Context, req *visionpb.DeleteReferenceImageRequest, opts ...gax.CallOption) error { 413 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 414 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 415 opts = append(c.CallOptions.DeleteReferenceImage[0:len(c.CallOptions.DeleteReferenceImage):len(c.CallOptions.DeleteReferenceImage)], opts...) 416 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 417 var err error 418 _, err = c.productSearchClient.DeleteReferenceImage(ctx, req, settings.GRPC...) 419 return err 420 }, opts...) 421 return err 422} 423 424// CreateReferenceImage creates and returns a new ReferenceImage resource. 425// 426// The bounding_poly field is optional. If bounding_poly is not specified, 427// the system will try to detect regions of interest in the image that are 428// compatible with the product_category on the parent product. If it is 429// specified, detection is ALWAYS skipped. The system converts polygons into 430// non-rotated rectangles. 431// 432// Note that the pipeline will resize the image if the image resolution is too 433// large to process (above 50MP). 434// 435// Possible errors: 436// 437// Returns INVALID_ARGUMENT if the image_uri is missing or longer than 4096 438// characters. 439// 440// Returns INVALID_ARGUMENT if the product does not exist. 441// 442// Returns INVALID_ARGUMENT if bounding_poly is not provided, and nothing 443// compatible with the parent product's product_category is detected. 444// 445// Returns INVALID_ARGUMENT if bounding_poly contains more than 10 polygons. 446func (c *ProductSearchClient) CreateReferenceImage(ctx context.Context, req *visionpb.CreateReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) { 447 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 448 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 449 opts = append(c.CallOptions.CreateReferenceImage[0:len(c.CallOptions.CreateReferenceImage):len(c.CallOptions.CreateReferenceImage)], opts...) 450 var resp *visionpb.ReferenceImage 451 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 452 var err error 453 resp, err = c.productSearchClient.CreateReferenceImage(ctx, req, settings.GRPC...) 454 return err 455 }, opts...) 456 if err != nil { 457 return nil, err 458 } 459 return resp, nil 460} 461 462// CreateProductSet creates and returns a new ProductSet resource. 463// 464// Possible errors: 465// 466// Returns INVALID_ARGUMENT if display_name is missing, or is longer than 467// 4096 characters. 468func (c *ProductSearchClient) CreateProductSet(ctx context.Context, req *visionpb.CreateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 469 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 470 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 471 opts = append(c.CallOptions.CreateProductSet[0:len(c.CallOptions.CreateProductSet):len(c.CallOptions.CreateProductSet)], opts...) 472 var resp *visionpb.ProductSet 473 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 474 var err error 475 resp, err = c.productSearchClient.CreateProductSet(ctx, req, settings.GRPC...) 476 return err 477 }, opts...) 478 if err != nil { 479 return nil, err 480 } 481 return resp, nil 482} 483 484// ListProductSets lists ProductSets in an unspecified order. 485// 486// Possible errors: 487// 488// Returns INVALID_ARGUMENT if page_size is greater than 100, or less 489// than 1. 490func (c *ProductSearchClient) ListProductSets(ctx context.Context, req *visionpb.ListProductSetsRequest, opts ...gax.CallOption) *ProductSetIterator { 491 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 492 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 493 opts = append(c.CallOptions.ListProductSets[0:len(c.CallOptions.ListProductSets):len(c.CallOptions.ListProductSets)], opts...) 494 it := &ProductSetIterator{} 495 req = proto.Clone(req).(*visionpb.ListProductSetsRequest) 496 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ProductSet, string, error) { 497 var resp *visionpb.ListProductSetsResponse 498 req.PageToken = pageToken 499 if pageSize > math.MaxInt32 { 500 req.PageSize = math.MaxInt32 501 } else { 502 req.PageSize = int32(pageSize) 503 } 504 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 505 var err error 506 resp, err = c.productSearchClient.ListProductSets(ctx, req, settings.GRPC...) 507 return err 508 }, opts...) 509 if err != nil { 510 return nil, "", err 511 } 512 return resp.ProductSets, resp.NextPageToken, nil 513 } 514 fetch := func(pageSize int, pageToken string) (string, error) { 515 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 516 if err != nil { 517 return "", err 518 } 519 it.items = append(it.items, items...) 520 return nextPageToken, nil 521 } 522 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 523 it.pageInfo.MaxSize = int(req.PageSize) 524 return it 525} 526 527// GetProductSet gets information associated with a ProductSet. 528// 529// Possible errors: 530// 531// Returns NOT_FOUND if the ProductSet does not exist. 532func (c *ProductSearchClient) GetProductSet(ctx context.Context, req *visionpb.GetProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 533 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 534 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 535 opts = append(c.CallOptions.GetProductSet[0:len(c.CallOptions.GetProductSet):len(c.CallOptions.GetProductSet)], opts...) 536 var resp *visionpb.ProductSet 537 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 538 var err error 539 resp, err = c.productSearchClient.GetProductSet(ctx, req, settings.GRPC...) 540 return err 541 }, opts...) 542 if err != nil { 543 return nil, err 544 } 545 return resp, nil 546} 547 548// UpdateProductSet makes changes to a ProductSet resource. 549// Only display_name can be updated currently. 550// 551// Possible errors: 552// 553// Returns NOT_FOUND if the ProductSet does not exist. 554// 555// Returns INVALID_ARGUMENT if display_name is present in update_mask but 556// missing from the request or longer than 4096 characters. 557func (c *ProductSearchClient) UpdateProductSet(ctx context.Context, req *visionpb.UpdateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 558 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product_set.name", req.GetProductSet().GetName())) 559 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 560 opts = append(c.CallOptions.UpdateProductSet[0:len(c.CallOptions.UpdateProductSet):len(c.CallOptions.UpdateProductSet)], opts...) 561 var resp *visionpb.ProductSet 562 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 563 var err error 564 resp, err = c.productSearchClient.UpdateProductSet(ctx, req, settings.GRPC...) 565 return err 566 }, opts...) 567 if err != nil { 568 return nil, err 569 } 570 return resp, nil 571} 572 573// DeleteProductSet permanently deletes a ProductSet. Products and ReferenceImages in the 574// ProductSet are not deleted. 575// 576// The actual image files are not deleted from Google Cloud Storage. 577// 578// Possible errors: 579// 580// Returns NOT_FOUND if the ProductSet does not exist. 581func (c *ProductSearchClient) DeleteProductSet(ctx context.Context, req *visionpb.DeleteProductSetRequest, opts ...gax.CallOption) error { 582 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 583 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 584 opts = append(c.CallOptions.DeleteProductSet[0:len(c.CallOptions.DeleteProductSet):len(c.CallOptions.DeleteProductSet)], opts...) 585 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 586 var err error 587 _, err = c.productSearchClient.DeleteProductSet(ctx, req, settings.GRPC...) 588 return err 589 }, opts...) 590 return err 591} 592 593// AddProductToProductSet adds a Product to the specified ProductSet. If the Product is already 594// present, no change is made. 595// 596// One Product can be added to at most 100 ProductSets. 597// 598// Possible errors: 599// 600// Returns NOT_FOUND if the Product or the ProductSet doesn't exist. 601func (c *ProductSearchClient) AddProductToProductSet(ctx context.Context, req *visionpb.AddProductToProductSetRequest, opts ...gax.CallOption) error { 602 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 603 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 604 opts = append(c.CallOptions.AddProductToProductSet[0:len(c.CallOptions.AddProductToProductSet):len(c.CallOptions.AddProductToProductSet)], opts...) 605 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 606 var err error 607 _, err = c.productSearchClient.AddProductToProductSet(ctx, req, settings.GRPC...) 608 return err 609 }, opts...) 610 return err 611} 612 613// RemoveProductFromProductSet removes a Product from the specified ProductSet. 614// 615// Possible errors: 616// 617// Returns NOT_FOUND If the Product is not found under the ProductSet. 618func (c *ProductSearchClient) RemoveProductFromProductSet(ctx context.Context, req *visionpb.RemoveProductFromProductSetRequest, opts ...gax.CallOption) error { 619 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 620 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 621 opts = append(c.CallOptions.RemoveProductFromProductSet[0:len(c.CallOptions.RemoveProductFromProductSet):len(c.CallOptions.RemoveProductFromProductSet)], opts...) 622 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 623 var err error 624 _, err = c.productSearchClient.RemoveProductFromProductSet(ctx, req, settings.GRPC...) 625 return err 626 }, opts...) 627 return err 628} 629 630// ListProductsInProductSet lists the Products in a ProductSet, in an unspecified order. If the 631// ProductSet does not exist, the products field of the response will be 632// empty. 633// 634// Possible errors: 635// 636// Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1. 637func (c *ProductSearchClient) ListProductsInProductSet(ctx context.Context, req *visionpb.ListProductsInProductSetRequest, opts ...gax.CallOption) *ProductIterator { 638 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 639 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 640 opts = append(c.CallOptions.ListProductsInProductSet[0:len(c.CallOptions.ListProductsInProductSet):len(c.CallOptions.ListProductsInProductSet)], opts...) 641 it := &ProductIterator{} 642 req = proto.Clone(req).(*visionpb.ListProductsInProductSetRequest) 643 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) { 644 var resp *visionpb.ListProductsInProductSetResponse 645 req.PageToken = pageToken 646 if pageSize > math.MaxInt32 { 647 req.PageSize = math.MaxInt32 648 } else { 649 req.PageSize = int32(pageSize) 650 } 651 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 652 var err error 653 resp, err = c.productSearchClient.ListProductsInProductSet(ctx, req, settings.GRPC...) 654 return err 655 }, opts...) 656 if err != nil { 657 return nil, "", err 658 } 659 return resp.Products, resp.NextPageToken, nil 660 } 661 fetch := func(pageSize int, pageToken string) (string, error) { 662 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 663 if err != nil { 664 return "", err 665 } 666 it.items = append(it.items, items...) 667 return nextPageToken, nil 668 } 669 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 670 it.pageInfo.MaxSize = int(req.PageSize) 671 return it 672} 673 674// ImportProductSets asynchronous API that imports a list of reference images to specified 675// product sets based on a list of image information. 676// 677// The [google.longrunning.Operation][google.longrunning.Operation] API can be 678// used to keep track of the progress and results of the request. 679// Operation.metadata contains BatchOperationMetadata. (progress) 680// Operation.response contains ImportProductSetsResponse. (results) 681// 682// The input source of this method is a csv file on Google Cloud Storage. 683// For the format of the csv file please see 684// [ImportProductSetsGcsSource.csv_file_uri][google.cloud.vision.v1.ImportProductSetsGcsSource.csv_file_uri]. 685func (c *ProductSearchClient) ImportProductSets(ctx context.Context, req *visionpb.ImportProductSetsRequest, opts ...gax.CallOption) (*ImportProductSetsOperation, error) { 686 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 687 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 688 opts = append(c.CallOptions.ImportProductSets[0:len(c.CallOptions.ImportProductSets):len(c.CallOptions.ImportProductSets)], opts...) 689 var resp *longrunningpb.Operation 690 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 691 var err error 692 resp, err = c.productSearchClient.ImportProductSets(ctx, req, settings.GRPC...) 693 return err 694 }, opts...) 695 if err != nil { 696 return nil, err 697 } 698 return &ImportProductSetsOperation{ 699 lro: longrunning.InternalNewOperation(c.LROClient, resp), 700 }, nil 701} 702 703// ProductIterator manages a stream of *visionpb.Product. 704type ProductIterator struct { 705 items []*visionpb.Product 706 pageInfo *iterator.PageInfo 707 nextFunc func() error 708 709 // InternalFetch is for use by the Google Cloud Libraries only. 710 // It is not part of the stable interface of this package. 711 // 712 // InternalFetch returns results from a single call to the underlying RPC. 713 // The number of results is no greater than pageSize. 714 // If there are no more results, nextPageToken is empty and err is nil. 715 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.Product, nextPageToken string, err error) 716} 717 718// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 719func (it *ProductIterator) PageInfo() *iterator.PageInfo { 720 return it.pageInfo 721} 722 723// Next returns the next result. Its second return value is iterator.Done if there are no more 724// results. Once Next returns Done, all subsequent calls will return Done. 725func (it *ProductIterator) Next() (*visionpb.Product, error) { 726 var item *visionpb.Product 727 if err := it.nextFunc(); err != nil { 728 return item, err 729 } 730 item = it.items[0] 731 it.items = it.items[1:] 732 return item, nil 733} 734 735func (it *ProductIterator) bufLen() int { 736 return len(it.items) 737} 738 739func (it *ProductIterator) takeBuf() interface{} { 740 b := it.items 741 it.items = nil 742 return b 743} 744 745// ProductSetIterator manages a stream of *visionpb.ProductSet. 746type ProductSetIterator struct { 747 items []*visionpb.ProductSet 748 pageInfo *iterator.PageInfo 749 nextFunc func() error 750 751 // InternalFetch is for use by the Google Cloud Libraries only. 752 // It is not part of the stable interface of this package. 753 // 754 // InternalFetch returns results from a single call to the underlying RPC. 755 // The number of results is no greater than pageSize. 756 // If there are no more results, nextPageToken is empty and err is nil. 757 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ProductSet, nextPageToken string, err error) 758} 759 760// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 761func (it *ProductSetIterator) PageInfo() *iterator.PageInfo { 762 return it.pageInfo 763} 764 765// Next returns the next result. Its second return value is iterator.Done if there are no more 766// results. Once Next returns Done, all subsequent calls will return Done. 767func (it *ProductSetIterator) Next() (*visionpb.ProductSet, error) { 768 var item *visionpb.ProductSet 769 if err := it.nextFunc(); err != nil { 770 return item, err 771 } 772 item = it.items[0] 773 it.items = it.items[1:] 774 return item, nil 775} 776 777func (it *ProductSetIterator) bufLen() int { 778 return len(it.items) 779} 780 781func (it *ProductSetIterator) takeBuf() interface{} { 782 b := it.items 783 it.items = nil 784 return b 785} 786 787// ReferenceImageIterator manages a stream of *visionpb.ReferenceImage. 788type ReferenceImageIterator struct { 789 items []*visionpb.ReferenceImage 790 pageInfo *iterator.PageInfo 791 nextFunc func() error 792 793 // InternalFetch is for use by the Google Cloud Libraries only. 794 // It is not part of the stable interface of this package. 795 // 796 // InternalFetch returns results from a single call to the underlying RPC. 797 // The number of results is no greater than pageSize. 798 // If there are no more results, nextPageToken is empty and err is nil. 799 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ReferenceImage, nextPageToken string, err error) 800} 801 802// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 803func (it *ReferenceImageIterator) PageInfo() *iterator.PageInfo { 804 return it.pageInfo 805} 806 807// Next returns the next result. Its second return value is iterator.Done if there are no more 808// results. Once Next returns Done, all subsequent calls will return Done. 809func (it *ReferenceImageIterator) Next() (*visionpb.ReferenceImage, error) { 810 var item *visionpb.ReferenceImage 811 if err := it.nextFunc(); err != nil { 812 return item, err 813 } 814 item = it.items[0] 815 it.items = it.items[1:] 816 return item, nil 817} 818 819func (it *ReferenceImageIterator) bufLen() int { 820 return len(it.items) 821} 822 823func (it *ReferenceImageIterator) takeBuf() interface{} { 824 b := it.items 825 it.items = nil 826 return b 827} 828 829// ImportProductSetsOperation manages a long-running operation from ImportProductSets. 830type ImportProductSetsOperation struct { 831 lro *longrunning.Operation 832} 833 834// ImportProductSetsOperation returns a new ImportProductSetsOperation from a given name. 835// The name must be that of a previously created ImportProductSetsOperation, possibly from a different process. 836func (c *ProductSearchClient) ImportProductSetsOperation(name string) *ImportProductSetsOperation { 837 return &ImportProductSetsOperation{ 838 lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}), 839 } 840} 841 842// Wait blocks until the long-running operation is completed, returning the response and any errors encountered. 843// 844// See documentation of Poll for error-handling information. 845func (op *ImportProductSetsOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) { 846 var resp visionpb.ImportProductSetsResponse 847 if err := op.lro.WaitWithInterval(ctx, &resp, 45000*time.Millisecond, opts...); err != nil { 848 return nil, err 849 } 850 return &resp, nil 851} 852 853// Poll fetches the latest state of the long-running operation. 854// 855// Poll also fetches the latest metadata, which can be retrieved by Metadata. 856// 857// If Poll fails, the error is returned and op is unmodified. If Poll succeeds and 858// the operation has completed with failure, the error is returned and op.Done will return true. 859// If Poll succeeds and the operation has completed successfully, 860// op.Done will return true, and the response of the operation is returned. 861// If Poll succeeds and the operation has not completed, the returned response and error are both nil. 862func (op *ImportProductSetsOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) { 863 var resp visionpb.ImportProductSetsResponse 864 if err := op.lro.Poll(ctx, &resp, opts...); err != nil { 865 return nil, err 866 } 867 if !op.Done() { 868 return nil, nil 869 } 870 return &resp, nil 871} 872 873// Metadata returns metadata associated with the long-running operation. 874// Metadata itself does not contact the server, but Poll does. 875// To get the latest metadata, call this method after a successful call to Poll. 876// If the metadata is not available, the returned metadata and error are both nil. 877func (op *ImportProductSetsOperation) Metadata() (*visionpb.BatchOperationMetadata, error) { 878 var meta visionpb.BatchOperationMetadata 879 if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata { 880 return nil, nil 881 } else if err != nil { 882 return nil, err 883 } 884 return &meta, nil 885} 886 887// Done reports whether the long-running operation has completed. 888func (op *ImportProductSetsOperation) Done() bool { 889 return op.lro.Done() 890} 891 892// Name returns the name of the long-running operation. 893// The name is assigned by the server and is unique within the service from which the operation is created. 894func (op *ImportProductSetsOperation) Name() string { 895 return op.lro.Name() 896} 897