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