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 CreateProductSet []gax.CallOption 42 ListProductSets []gax.CallOption 43 GetProductSet []gax.CallOption 44 UpdateProductSet []gax.CallOption 45 DeleteProductSet []gax.CallOption 46 CreateProduct []gax.CallOption 47 ListProducts []gax.CallOption 48 GetProduct []gax.CallOption 49 UpdateProduct []gax.CallOption 50 DeleteProduct []gax.CallOption 51 CreateReferenceImage []gax.CallOption 52 DeleteReferenceImage []gax.CallOption 53 ListReferenceImages []gax.CallOption 54 GetReferenceImage []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 CreateProductSet: retry[[2]string{"default", "non_idempotent"}], 85 ListProductSets: retry[[2]string{"default", "idempotent"}], 86 GetProductSet: retry[[2]string{"default", "idempotent"}], 87 UpdateProductSet: retry[[2]string{"default", "idempotent"}], 88 DeleteProductSet: retry[[2]string{"default", "idempotent"}], 89 CreateProduct: retry[[2]string{"default", "non_idempotent"}], 90 ListProducts: retry[[2]string{"default", "idempotent"}], 91 GetProduct: retry[[2]string{"default", "idempotent"}], 92 UpdateProduct: retry[[2]string{"default", "idempotent"}], 93 DeleteProduct: retry[[2]string{"default", "idempotent"}], 94 CreateReferenceImage: retry[[2]string{"default", "non_idempotent"}], 95 DeleteReferenceImage: retry[[2]string{"default", "idempotent"}], 96 ListReferenceImages: retry[[2]string{"default", "idempotent"}], 97 GetReferenceImage: 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// CreateProductSet creates and returns a new ProductSet resource. 192// 193// Possible errors: 194// 195// Returns INVALID_ARGUMENT if display_name is missing, or is longer than 196// 4096 characters. 197func (c *ProductSearchClient) CreateProductSet(ctx context.Context, req *visionpb.CreateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 198 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 199 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 200 opts = append(c.CallOptions.CreateProductSet[0:len(c.CallOptions.CreateProductSet):len(c.CallOptions.CreateProductSet)], opts...) 201 var resp *visionpb.ProductSet 202 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 203 var err error 204 resp, err = c.productSearchClient.CreateProductSet(ctx, req, settings.GRPC...) 205 return err 206 }, opts...) 207 if err != nil { 208 return nil, err 209 } 210 return resp, nil 211} 212 213// ListProductSets lists ProductSets in an unspecified order. 214// 215// Possible errors: 216// 217// Returns INVALID_ARGUMENT if page_size is greater than 100, or less 218// than 1. 219func (c *ProductSearchClient) ListProductSets(ctx context.Context, req *visionpb.ListProductSetsRequest, opts ...gax.CallOption) *ProductSetIterator { 220 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 221 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 222 opts = append(c.CallOptions.ListProductSets[0:len(c.CallOptions.ListProductSets):len(c.CallOptions.ListProductSets)], opts...) 223 it := &ProductSetIterator{} 224 req = proto.Clone(req).(*visionpb.ListProductSetsRequest) 225 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ProductSet, string, error) { 226 var resp *visionpb.ListProductSetsResponse 227 req.PageToken = pageToken 228 if pageSize > math.MaxInt32 { 229 req.PageSize = math.MaxInt32 230 } else { 231 req.PageSize = int32(pageSize) 232 } 233 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 234 var err error 235 resp, err = c.productSearchClient.ListProductSets(ctx, req, settings.GRPC...) 236 return err 237 }, opts...) 238 if err != nil { 239 return nil, "", err 240 } 241 return resp.ProductSets, resp.NextPageToken, nil 242 } 243 fetch := func(pageSize int, pageToken string) (string, error) { 244 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 245 if err != nil { 246 return "", err 247 } 248 it.items = append(it.items, items...) 249 return nextPageToken, nil 250 } 251 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 252 it.pageInfo.MaxSize = int(req.PageSize) 253 it.pageInfo.Token = req.PageToken 254 return it 255} 256 257// GetProductSet gets information associated with a ProductSet. 258// 259// Possible errors: 260// 261// Returns NOT_FOUND if the ProductSet does not exist. 262func (c *ProductSearchClient) GetProductSet(ctx context.Context, req *visionpb.GetProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 263 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 264 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 265 opts = append(c.CallOptions.GetProductSet[0:len(c.CallOptions.GetProductSet):len(c.CallOptions.GetProductSet)], opts...) 266 var resp *visionpb.ProductSet 267 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 268 var err error 269 resp, err = c.productSearchClient.GetProductSet(ctx, req, settings.GRPC...) 270 return err 271 }, opts...) 272 if err != nil { 273 return nil, err 274 } 275 return resp, nil 276} 277 278// UpdateProductSet makes changes to a ProductSet resource. 279// Only display_name can be updated currently. 280// 281// Possible errors: 282// 283// Returns NOT_FOUND if the ProductSet does not exist. 284// 285// Returns INVALID_ARGUMENT if display_name is present in update_mask but 286// missing from the request or longer than 4096 characters. 287func (c *ProductSearchClient) UpdateProductSet(ctx context.Context, req *visionpb.UpdateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) { 288 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product_set.name", req.GetProductSet().GetName())) 289 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 290 opts = append(c.CallOptions.UpdateProductSet[0:len(c.CallOptions.UpdateProductSet):len(c.CallOptions.UpdateProductSet)], opts...) 291 var resp *visionpb.ProductSet 292 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 293 var err error 294 resp, err = c.productSearchClient.UpdateProductSet(ctx, req, settings.GRPC...) 295 return err 296 }, opts...) 297 if err != nil { 298 return nil, err 299 } 300 return resp, nil 301} 302 303// DeleteProductSet permanently deletes a ProductSet. Products and ReferenceImages in the 304// ProductSet are not deleted. 305// 306// The actual image files are not deleted from Google Cloud Storage. 307func (c *ProductSearchClient) DeleteProductSet(ctx context.Context, req *visionpb.DeleteProductSetRequest, opts ...gax.CallOption) error { 308 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 309 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 310 opts = append(c.CallOptions.DeleteProductSet[0:len(c.CallOptions.DeleteProductSet):len(c.CallOptions.DeleteProductSet)], opts...) 311 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 312 var err error 313 _, err = c.productSearchClient.DeleteProductSet(ctx, req, settings.GRPC...) 314 return err 315 }, opts...) 316 return err 317} 318 319// CreateProduct creates and returns a new product resource. 320// 321// Possible errors: 322// 323// Returns INVALID_ARGUMENT if display_name is missing or longer than 4096 324// characters. 325// 326// Returns INVALID_ARGUMENT if description is longer than 4096 characters. 327// 328// Returns INVALID_ARGUMENT if product_category is missing or invalid. 329func (c *ProductSearchClient) CreateProduct(ctx context.Context, req *visionpb.CreateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 330 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 331 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 332 opts = append(c.CallOptions.CreateProduct[0:len(c.CallOptions.CreateProduct):len(c.CallOptions.CreateProduct)], opts...) 333 var resp *visionpb.Product 334 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 335 var err error 336 resp, err = c.productSearchClient.CreateProduct(ctx, req, settings.GRPC...) 337 return err 338 }, opts...) 339 if err != nil { 340 return nil, err 341 } 342 return resp, nil 343} 344 345// ListProducts lists products in an unspecified order. 346// 347// Possible errors: 348// 349// Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1. 350func (c *ProductSearchClient) ListProducts(ctx context.Context, req *visionpb.ListProductsRequest, opts ...gax.CallOption) *ProductIterator { 351 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 352 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 353 opts = append(c.CallOptions.ListProducts[0:len(c.CallOptions.ListProducts):len(c.CallOptions.ListProducts)], opts...) 354 it := &ProductIterator{} 355 req = proto.Clone(req).(*visionpb.ListProductsRequest) 356 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) { 357 var resp *visionpb.ListProductsResponse 358 req.PageToken = pageToken 359 if pageSize > math.MaxInt32 { 360 req.PageSize = math.MaxInt32 361 } else { 362 req.PageSize = int32(pageSize) 363 } 364 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 365 var err error 366 resp, err = c.productSearchClient.ListProducts(ctx, req, settings.GRPC...) 367 return err 368 }, opts...) 369 if err != nil { 370 return nil, "", err 371 } 372 return resp.Products, resp.NextPageToken, nil 373 } 374 fetch := func(pageSize int, pageToken string) (string, error) { 375 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 376 if err != nil { 377 return "", err 378 } 379 it.items = append(it.items, items...) 380 return nextPageToken, nil 381 } 382 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 383 it.pageInfo.MaxSize = int(req.PageSize) 384 it.pageInfo.Token = req.PageToken 385 return it 386} 387 388// GetProduct gets information associated with a Product. 389// 390// Possible errors: 391// 392// Returns NOT_FOUND if the Product does not exist. 393func (c *ProductSearchClient) GetProduct(ctx context.Context, req *visionpb.GetProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 394 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 395 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 396 opts = append(c.CallOptions.GetProduct[0:len(c.CallOptions.GetProduct):len(c.CallOptions.GetProduct)], opts...) 397 var resp *visionpb.Product 398 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 399 var err error 400 resp, err = c.productSearchClient.GetProduct(ctx, req, settings.GRPC...) 401 return err 402 }, opts...) 403 if err != nil { 404 return nil, err 405 } 406 return resp, nil 407} 408 409// UpdateProduct makes changes to a Product resource. 410// Only the display_name, description, and labels fields can be updated 411// right now. 412// 413// If labels are updated, the change will not be reflected in queries until 414// the next index time. 415// 416// Possible errors: 417// 418// Returns NOT_FOUND if the Product does not exist. 419// 420// Returns INVALID_ARGUMENT if display_name is present in update_mask but is 421// missing from the request or longer than 4096 characters. 422// 423// Returns INVALID_ARGUMENT if description is present in update_mask but is 424// longer than 4096 characters. 425// 426// Returns INVALID_ARGUMENT if product_category is present in update_mask. 427func (c *ProductSearchClient) UpdateProduct(ctx context.Context, req *visionpb.UpdateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) { 428 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product.name", req.GetProduct().GetName())) 429 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 430 opts = append(c.CallOptions.UpdateProduct[0:len(c.CallOptions.UpdateProduct):len(c.CallOptions.UpdateProduct)], opts...) 431 var resp *visionpb.Product 432 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 433 var err error 434 resp, err = c.productSearchClient.UpdateProduct(ctx, req, settings.GRPC...) 435 return err 436 }, opts...) 437 if err != nil { 438 return nil, err 439 } 440 return resp, nil 441} 442 443// DeleteProduct permanently deletes a product and its reference images. 444// 445// Metadata of the product and all its images will be deleted right away, but 446// search queries against ProductSets containing the product may still work 447// until all related caches are refreshed. 448func (c *ProductSearchClient) DeleteProduct(ctx context.Context, req *visionpb.DeleteProductRequest, opts ...gax.CallOption) error { 449 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 450 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 451 opts = append(c.CallOptions.DeleteProduct[0:len(c.CallOptions.DeleteProduct):len(c.CallOptions.DeleteProduct)], opts...) 452 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 453 var err error 454 _, err = c.productSearchClient.DeleteProduct(ctx, req, settings.GRPC...) 455 return err 456 }, opts...) 457 return err 458} 459 460// CreateReferenceImage creates and returns a new ReferenceImage resource. 461// 462// The bounding_poly field is optional. If bounding_poly is not specified, 463// the system will try to detect regions of interest in the image that are 464// compatible with the product_category on the parent product. If it is 465// specified, detection is ALWAYS skipped. The system converts polygons into 466// non-rotated rectangles. 467// 468// Note that the pipeline will resize the image if the image resolution is too 469// large to process (above 50MP). 470// 471// Possible errors: 472// 473// Returns INVALID_ARGUMENT if the image_uri is missing or longer than 4096 474// characters. 475// 476// Returns INVALID_ARGUMENT if the product does not exist. 477// 478// Returns INVALID_ARGUMENT if bounding_poly is not provided, and nothing 479// compatible with the parent product's product_category is detected. 480// 481// Returns INVALID_ARGUMENT if bounding_poly contains more than 10 polygons. 482func (c *ProductSearchClient) CreateReferenceImage(ctx context.Context, req *visionpb.CreateReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) { 483 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 484 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 485 opts = append(c.CallOptions.CreateReferenceImage[0:len(c.CallOptions.CreateReferenceImage):len(c.CallOptions.CreateReferenceImage)], opts...) 486 var resp *visionpb.ReferenceImage 487 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 488 var err error 489 resp, err = c.productSearchClient.CreateReferenceImage(ctx, req, settings.GRPC...) 490 return err 491 }, opts...) 492 if err != nil { 493 return nil, err 494 } 495 return resp, nil 496} 497 498// DeleteReferenceImage permanently deletes a reference image. 499// 500// The image metadata will be deleted right away, but search queries 501// against ProductSets containing the image may still work until all related 502// caches are refreshed. 503// 504// The actual image files are not deleted from Google Cloud Storage. 505func (c *ProductSearchClient) DeleteReferenceImage(ctx context.Context, req *visionpb.DeleteReferenceImageRequest, opts ...gax.CallOption) error { 506 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 507 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 508 opts = append(c.CallOptions.DeleteReferenceImage[0:len(c.CallOptions.DeleteReferenceImage):len(c.CallOptions.DeleteReferenceImage)], opts...) 509 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 510 var err error 511 _, err = c.productSearchClient.DeleteReferenceImage(ctx, req, settings.GRPC...) 512 return err 513 }, opts...) 514 return err 515} 516 517// ListReferenceImages lists reference images. 518// 519// Possible errors: 520// 521// Returns NOT_FOUND if the parent product does not exist. 522// 523// Returns INVALID_ARGUMENT if the page_size is greater than 100, or less 524// than 1. 525func (c *ProductSearchClient) ListReferenceImages(ctx context.Context, req *visionpb.ListReferenceImagesRequest, opts ...gax.CallOption) *ReferenceImageIterator { 526 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 527 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 528 opts = append(c.CallOptions.ListReferenceImages[0:len(c.CallOptions.ListReferenceImages):len(c.CallOptions.ListReferenceImages)], opts...) 529 it := &ReferenceImageIterator{} 530 req = proto.Clone(req).(*visionpb.ListReferenceImagesRequest) 531 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ReferenceImage, string, error) { 532 var resp *visionpb.ListReferenceImagesResponse 533 req.PageToken = pageToken 534 if pageSize > math.MaxInt32 { 535 req.PageSize = math.MaxInt32 536 } else { 537 req.PageSize = int32(pageSize) 538 } 539 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 540 var err error 541 resp, err = c.productSearchClient.ListReferenceImages(ctx, req, settings.GRPC...) 542 return err 543 }, opts...) 544 if err != nil { 545 return nil, "", err 546 } 547 return resp.ReferenceImages, resp.NextPageToken, nil 548 } 549 fetch := func(pageSize int, pageToken string) (string, error) { 550 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 551 if err != nil { 552 return "", err 553 } 554 it.items = append(it.items, items...) 555 return nextPageToken, nil 556 } 557 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 558 it.pageInfo.MaxSize = int(req.PageSize) 559 it.pageInfo.Token = req.PageToken 560 return it 561} 562 563// GetReferenceImage gets information associated with a ReferenceImage. 564// 565// Possible errors: 566// 567// Returns NOT_FOUND if the specified image does not exist. 568func (c *ProductSearchClient) GetReferenceImage(ctx context.Context, req *visionpb.GetReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) { 569 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 570 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 571 opts = append(c.CallOptions.GetReferenceImage[0:len(c.CallOptions.GetReferenceImage):len(c.CallOptions.GetReferenceImage)], opts...) 572 var resp *visionpb.ReferenceImage 573 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 574 var err error 575 resp, err = c.productSearchClient.GetReferenceImage(ctx, req, settings.GRPC...) 576 return err 577 }, opts...) 578 if err != nil { 579 return nil, err 580 } 581 return resp, nil 582} 583 584// AddProductToProductSet adds a Product to the specified ProductSet. If the Product is already 585// present, no change is made. 586// 587// One Product can be added to at most 100 ProductSets. 588// 589// Possible errors: 590// 591// Returns NOT_FOUND if the Product or the ProductSet doesn't exist. 592func (c *ProductSearchClient) AddProductToProductSet(ctx context.Context, req *visionpb.AddProductToProductSetRequest, opts ...gax.CallOption) error { 593 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 594 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 595 opts = append(c.CallOptions.AddProductToProductSet[0:len(c.CallOptions.AddProductToProductSet):len(c.CallOptions.AddProductToProductSet)], opts...) 596 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 597 var err error 598 _, err = c.productSearchClient.AddProductToProductSet(ctx, req, settings.GRPC...) 599 return err 600 }, opts...) 601 return err 602} 603 604// RemoveProductFromProductSet removes a Product from the specified ProductSet. 605func (c *ProductSearchClient) RemoveProductFromProductSet(ctx context.Context, req *visionpb.RemoveProductFromProductSetRequest, opts ...gax.CallOption) error { 606 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 607 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 608 opts = append(c.CallOptions.RemoveProductFromProductSet[0:len(c.CallOptions.RemoveProductFromProductSet):len(c.CallOptions.RemoveProductFromProductSet)], opts...) 609 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 610 var err error 611 _, err = c.productSearchClient.RemoveProductFromProductSet(ctx, req, settings.GRPC...) 612 return err 613 }, opts...) 614 return err 615} 616 617// ListProductsInProductSet lists the Products in a ProductSet, in an unspecified order. If the 618// ProductSet does not exist, the products field of the response will be 619// empty. 620// 621// Possible errors: 622// 623// Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1. 624func (c *ProductSearchClient) ListProductsInProductSet(ctx context.Context, req *visionpb.ListProductsInProductSetRequest, opts ...gax.CallOption) *ProductIterator { 625 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName())) 626 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 627 opts = append(c.CallOptions.ListProductsInProductSet[0:len(c.CallOptions.ListProductsInProductSet):len(c.CallOptions.ListProductsInProductSet)], opts...) 628 it := &ProductIterator{} 629 req = proto.Clone(req).(*visionpb.ListProductsInProductSetRequest) 630 it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) { 631 var resp *visionpb.ListProductsInProductSetResponse 632 req.PageToken = pageToken 633 if pageSize > math.MaxInt32 { 634 req.PageSize = math.MaxInt32 635 } else { 636 req.PageSize = int32(pageSize) 637 } 638 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 639 var err error 640 resp, err = c.productSearchClient.ListProductsInProductSet(ctx, req, settings.GRPC...) 641 return err 642 }, opts...) 643 if err != nil { 644 return nil, "", err 645 } 646 return resp.Products, resp.NextPageToken, nil 647 } 648 fetch := func(pageSize int, pageToken string) (string, error) { 649 items, nextPageToken, err := it.InternalFetch(pageSize, pageToken) 650 if err != nil { 651 return "", err 652 } 653 it.items = append(it.items, items...) 654 return nextPageToken, nil 655 } 656 it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf) 657 it.pageInfo.MaxSize = int(req.PageSize) 658 it.pageInfo.Token = req.PageToken 659 return it 660} 661 662// ImportProductSets asynchronous API that imports a list of reference images to specified 663// product sets based on a list of image information. 664// 665// The [google.longrunning.Operation][google.longrunning.Operation] API can be 666// used to keep track of the progress and results of the request. 667// Operation.metadata contains BatchOperationMetadata. (progress) 668// Operation.response contains ImportProductSetsResponse. (results) 669// 670// The input source of this method is a csv file on Google Cloud Storage. 671// For the format of the csv file please see 672// [ImportProductSetsGcsSource.csv_file_uri][google.cloud.vision.v1.ImportProductSetsGcsSource.csv_file_uri]. 673func (c *ProductSearchClient) ImportProductSets(ctx context.Context, req *visionpb.ImportProductSetsRequest, opts ...gax.CallOption) (*ImportProductSetsOperation, error) { 674 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent())) 675 ctx = insertMetadata(ctx, c.xGoogMetadata, md) 676 opts = append(c.CallOptions.ImportProductSets[0:len(c.CallOptions.ImportProductSets):len(c.CallOptions.ImportProductSets)], opts...) 677 var resp *longrunningpb.Operation 678 err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error { 679 var err error 680 resp, err = c.productSearchClient.ImportProductSets(ctx, req, settings.GRPC...) 681 return err 682 }, opts...) 683 if err != nil { 684 return nil, err 685 } 686 return &ImportProductSetsOperation{ 687 lro: longrunning.InternalNewOperation(c.LROClient, resp), 688 }, nil 689} 690 691// ProductIterator manages a stream of *visionpb.Product. 692type ProductIterator struct { 693 items []*visionpb.Product 694 pageInfo *iterator.PageInfo 695 nextFunc func() error 696 697 // InternalFetch is for use by the Google Cloud Libraries only. 698 // It is not part of the stable interface of this package. 699 // 700 // InternalFetch returns results from a single call to the underlying RPC. 701 // The number of results is no greater than pageSize. 702 // If there are no more results, nextPageToken is empty and err is nil. 703 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.Product, nextPageToken string, err error) 704} 705 706// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 707func (it *ProductIterator) PageInfo() *iterator.PageInfo { 708 return it.pageInfo 709} 710 711// Next returns the next result. Its second return value is iterator.Done if there are no more 712// results. Once Next returns Done, all subsequent calls will return Done. 713func (it *ProductIterator) Next() (*visionpb.Product, error) { 714 var item *visionpb.Product 715 if err := it.nextFunc(); err != nil { 716 return item, err 717 } 718 item = it.items[0] 719 it.items = it.items[1:] 720 return item, nil 721} 722 723func (it *ProductIterator) bufLen() int { 724 return len(it.items) 725} 726 727func (it *ProductIterator) takeBuf() interface{} { 728 b := it.items 729 it.items = nil 730 return b 731} 732 733// ProductSetIterator manages a stream of *visionpb.ProductSet. 734type ProductSetIterator struct { 735 items []*visionpb.ProductSet 736 pageInfo *iterator.PageInfo 737 nextFunc func() error 738 739 // InternalFetch is for use by the Google Cloud Libraries only. 740 // It is not part of the stable interface of this package. 741 // 742 // InternalFetch returns results from a single call to the underlying RPC. 743 // The number of results is no greater than pageSize. 744 // If there are no more results, nextPageToken is empty and err is nil. 745 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ProductSet, nextPageToken string, err error) 746} 747 748// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 749func (it *ProductSetIterator) PageInfo() *iterator.PageInfo { 750 return it.pageInfo 751} 752 753// Next returns the next result. Its second return value is iterator.Done if there are no more 754// results. Once Next returns Done, all subsequent calls will return Done. 755func (it *ProductSetIterator) Next() (*visionpb.ProductSet, error) { 756 var item *visionpb.ProductSet 757 if err := it.nextFunc(); err != nil { 758 return item, err 759 } 760 item = it.items[0] 761 it.items = it.items[1:] 762 return item, nil 763} 764 765func (it *ProductSetIterator) bufLen() int { 766 return len(it.items) 767} 768 769func (it *ProductSetIterator) takeBuf() interface{} { 770 b := it.items 771 it.items = nil 772 return b 773} 774 775// ReferenceImageIterator manages a stream of *visionpb.ReferenceImage. 776type ReferenceImageIterator struct { 777 items []*visionpb.ReferenceImage 778 pageInfo *iterator.PageInfo 779 nextFunc func() error 780 781 // InternalFetch is for use by the Google Cloud Libraries only. 782 // It is not part of the stable interface of this package. 783 // 784 // InternalFetch returns results from a single call to the underlying RPC. 785 // The number of results is no greater than pageSize. 786 // If there are no more results, nextPageToken is empty and err is nil. 787 InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ReferenceImage, nextPageToken string, err error) 788} 789 790// PageInfo supports pagination. See the google.golang.org/api/iterator package for details. 791func (it *ReferenceImageIterator) PageInfo() *iterator.PageInfo { 792 return it.pageInfo 793} 794 795// Next returns the next result. Its second return value is iterator.Done if there are no more 796// results. Once Next returns Done, all subsequent calls will return Done. 797func (it *ReferenceImageIterator) Next() (*visionpb.ReferenceImage, error) { 798 var item *visionpb.ReferenceImage 799 if err := it.nextFunc(); err != nil { 800 return item, err 801 } 802 item = it.items[0] 803 it.items = it.items[1:] 804 return item, nil 805} 806 807func (it *ReferenceImageIterator) bufLen() int { 808 return len(it.items) 809} 810 811func (it *ReferenceImageIterator) takeBuf() interface{} { 812 b := it.items 813 it.items = nil 814 return b 815} 816 817// ImportProductSetsOperation manages a long-running operation from ImportProductSets. 818type ImportProductSetsOperation struct { 819 lro *longrunning.Operation 820} 821 822// ImportProductSetsOperation returns a new ImportProductSetsOperation from a given name. 823// The name must be that of a previously created ImportProductSetsOperation, possibly from a different process. 824func (c *ProductSearchClient) ImportProductSetsOperation(name string) *ImportProductSetsOperation { 825 return &ImportProductSetsOperation{ 826 lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}), 827 } 828} 829 830// Wait blocks until the long-running operation is completed, returning the response and any errors encountered. 831// 832// See documentation of Poll for error-handling information. 833func (op *ImportProductSetsOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) { 834 var resp visionpb.ImportProductSetsResponse 835 if err := op.lro.WaitWithInterval(ctx, &resp, 45000*time.Millisecond, opts...); err != nil { 836 return nil, err 837 } 838 return &resp, nil 839} 840 841// Poll fetches the latest state of the long-running operation. 842// 843// Poll also fetches the latest metadata, which can be retrieved by Metadata. 844// 845// If Poll fails, the error is returned and op is unmodified. If Poll succeeds and 846// the operation has completed with failure, the error is returned and op.Done will return true. 847// If Poll succeeds and the operation has completed successfully, 848// op.Done will return true, and the response of the operation is returned. 849// If Poll succeeds and the operation has not completed, the returned response and error are both nil. 850func (op *ImportProductSetsOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) { 851 var resp visionpb.ImportProductSetsResponse 852 if err := op.lro.Poll(ctx, &resp, opts...); err != nil { 853 return nil, err 854 } 855 if !op.Done() { 856 return nil, nil 857 } 858 return &resp, nil 859} 860 861// Metadata returns metadata associated with the long-running operation. 862// Metadata itself does not contact the server, but Poll does. 863// To get the latest metadata, call this method after a successful call to Poll. 864// If the metadata is not available, the returned metadata and error are both nil. 865func (op *ImportProductSetsOperation) Metadata() (*visionpb.BatchOperationMetadata, error) { 866 var meta visionpb.BatchOperationMetadata 867 if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata { 868 return nil, nil 869 } else if err != nil { 870 return nil, err 871 } 872 return &meta, nil 873} 874 875// Done reports whether the long-running operation has completed. 876func (op *ImportProductSetsOperation) Done() bool { 877 return op.lro.Done() 878} 879 880// Name returns the name of the long-running operation. 881// The name is assigned by the server and is unique within the service from which the operation is created. 882func (op *ImportProductSetsOperation) Name() string { 883 return op.lro.Name() 884} 885