diff --git a/src/main/java/com/google/api/codegen/transformer/go/GoGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/go/GoGapicSurfaceTransformer.java index a3d382fed7..2f4749c93f 100644 --- a/src/main/java/com/google/api/codegen/transformer/go/GoGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/go/GoGapicSurfaceTransformer.java @@ -390,7 +390,9 @@ private enum ImportKind { .put( ImportContext.CLIENT, ImportKind.LRO, - ImmutableList.of("cloud.google.com/go/longrunning;;;")) + ImmutableList.of( + "cloud.google.com/go/longrunning;;;", + "cloud.google.com/go/longrunning/autogen;lroauto;;")) .put( ImportContext.EXAMPLE, ImportKind.SERVER_STREAM, diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticLangClientFileView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticLangClientFileView.java index e8542dc248..f2675a4c6e 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticLangClientFileView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticLangClientFileView.java @@ -71,6 +71,10 @@ public String resourceRoot() { public abstract List lroDetailViews(); + public boolean hasLongRunningOperations() { + return !lroDetailViews().isEmpty(); + } + public static Builder newBuilder() { return new AutoValue_StaticLangClientFileView.Builder(); } diff --git a/src/main/resources/com/google/api/codegen/go/main.snip b/src/main/resources/com/google/api/codegen/go/main.snip index e82f0cde4e..07924cfa23 100644 --- a/src/main/resources/com/google/api/codegen/go/main.snip +++ b/src/main/resources/com/google/api/codegen/go/main.snip @@ -66,6 +66,13 @@ {@stub.name} {@stub.grpcClientTypeName} @end + @if view.hasLongRunningOperations + // LROClient is used internally to handle longrunning operations. + // It is exposed so that its CallOptions can be modified if required. + // Users should not Close this client. + LROClient *lroauto.OperationsClient + @end + // The call options for this service. CallOptions *{@view.callOptionsTypeName} @@ -93,6 +100,13 @@ @end } c.SetGoogleClientInfo() + @if view.hasLongRunningOperations + + c.LROClient, err = lroauto.NewOperationsClient(ctx, option.WithGRPCConn(conn)) + if err != nil { + panic("unexpected error creating LRO client: " + err.Error()) + } + @end return c, nil } @@ -208,8 +222,7 @@ return nil, err } return &{@method.operationMethod.clientReturnTypeName}{ - lro: longrunning.InternalNewOperation(c.Connection(), resp), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, resp), }, nil } @end @@ -328,25 +341,16 @@ @end @private lroWrapper(view, lro) - @if lro.isEmptyOperation - // {@lro.clientReturnTypeName} manages a long-running operation with no result. - @else - // {@lro.clientReturnTypeName} manages a long-running operation from {@lro.methodName}. - @end - + // {@lro.clientReturnTypeName} manages a long-running operation from {@lro.methodName}. type {@lro.clientReturnTypeName} struct { lro *longrunning.Operation - - // The metadata to be sent with each request. - xGoogHeader []string } // {@lro.constructorName} returns a new {@lro.clientReturnTypeName} from a given name. // The name must be that of a previously created {@lro.clientReturnTypeName}, possibly from a different process. func (c *{@view.clientTypeName}) {@lro.constructorName}(name string) *{@lro.clientReturnTypeName} { return &{@lro.clientReturnTypeName}{ - lro: longrunning.InternalNewOperation(c.Connection(), &longrunningpb.Operation{Name: name}), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}), } } @@ -354,9 +358,8 @@ // Wait blocks until the long-running operation is completed, returning any error encountered. // // See documentation of Poll for error-handling information. - func (op *{@lro.clientReturnTypeName}) Wait(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Wait(ctx, nil) + func (op *{@lro.clientReturnTypeName}) Wait(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Wait(ctx, nil, opts...) } // Poll fetches the latest state of the long-running operation. @@ -366,18 +369,16 @@ // If Poll fails, the error is returned and op is unmodified. If Poll succeeds and // the operation has completed with failure, the error is returned and op.Done will return true. // If Poll succeeds and the operation has completed successfully, op.Done will return true. - func (op *{@lro.clientReturnTypeName}) Poll(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Poll(ctx, nil) + func (op *{@lro.clientReturnTypeName}) Poll(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Poll(ctx, nil, opts...) } @else // Wait blocks until the long-running operation is completed, returning the response and any errors encountered. // // See documentation of Poll for error-handling information. - func (op *{@lro.clientReturnTypeName}) Wait(ctx context.Context) (*{@lro.operationPayloadTypeName}, error) { + func (op *{@lro.clientReturnTypeName}) Wait(ctx context.Context, opts ...gax.CallOption) (*{@lro.operationPayloadTypeName}, error) { var resp {@lro.operationPayloadTypeName} - ctx = insertXGoog(ctx, op.xGoogHeader) - if err := op.lro.Wait(ctx, &resp); err != nil { + if err := op.lro.Wait(ctx, &resp, opts...); err != nil { return nil, err } return &resp, nil @@ -392,10 +393,9 @@ // If Poll succeeds and the operation has completed successfully, // op.Done will return true, and the response of the operation is returned. // If Poll succeeds and the operation has not completed, the returned response and error are both nil. - func (op *{@lro.clientReturnTypeName}) Poll(ctx context.Context) (*{@lro.operationPayloadTypeName}, error) { + func (op *{@lro.clientReturnTypeName}) Poll(ctx context.Context, opts ...gax.CallOption) (*{@lro.operationPayloadTypeName}, error) { var resp {@lro.operationPayloadTypeName} - ctx = insertXGoog(ctx, op.xGoogHeader) - if err := op.lro.Poll(ctx, &resp); err != nil { + if err := op.lro.Poll(ctx, &resp, opts...); err != nil { return nil, err } if !op.Done() { @@ -436,9 +436,8 @@ // Clients can use Poll or other methods to check whether the cancellation succeeded or whether the operation // completed despite cancellation. On successful cancellation, the operation is not deleted; // instead, op.Poll returns an error with code Canceled. - func (op *{@lro.clientReturnTypeName}) Cancel(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Cancel(ctx) + func (op *{@lro.clientReturnTypeName}) Cancel(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Cancel(ctx, opts...) } @end @@ -446,9 +445,8 @@ // Delete deletes a long-running operation. // This method indicates that the client is no longer interested in the operation result. // It does not cancel the operation. - func (op *{@lro.clientReturnTypeName}) Delete(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Delete(ctx) + func (op *{@lro.clientReturnTypeName}) Delete(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Delete(ctx, opts...) } @end @end diff --git a/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline index dfa64a8236..f6389b73cf 100644 --- a/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline @@ -24,6 +24,7 @@ import ( "cloud.google.com/go/iam" "cloud.google.com/go/internal/version" "cloud.google.com/go/longrunning" + lroauto "cloud.google.com/go/longrunning/autogen" gax "github.com/googleapis/gax-go" "golang.org/x/net/context" "google.golang.org/api/iterator" @@ -133,6 +134,11 @@ type Client struct { client librarypb.LibraryServiceClient labelerClient taggerpb.LabelerClient + // LROClient is used internally to handle longrunning operations. + // It is exposed so that its CallOptions can be modified if required. + // Users should not Close this client. + LROClient *lroauto.OperationsClient + // The call options for this service. CallOptions *CallOptions @@ -171,6 +177,11 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error labelerClient: taggerpb.NewLabelerClient(conn), } c.SetGoogleClientInfo() + + c.LROClient, err = lroauto.NewOperationsClient(ctx, option.WithGRPCConn(conn)) + if err != nil { + panic("unexpected error creating LRO client: " + err.Error()) + } return c, nil } @@ -685,8 +696,7 @@ func (c *Client) GetBigBook(ctx context.Context, req *librarypb.GetBookRequest, return nil, err } return &GetBigBookOperation{ - lro: longrunning.InternalNewOperation(c.Connection(), resp), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, resp), }, nil } @@ -704,8 +714,7 @@ func (c *Client) GetBigNothing(ctx context.Context, req *librarypb.GetBookReques return nil, err } return &GetBigNothingOperation{ - lro: longrunning.InternalNewOperation(c.Connection(), resp), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, resp), }, nil } @@ -856,27 +865,22 @@ func (it *StringIterator) takeBuf() interface{} { // GetBigBookOperation manages a long-running operation from GetBigBook. type GetBigBookOperation struct { lro *longrunning.Operation - - // The metadata to be sent with each request. - xGoogHeader []string } // GetBigBookOperation returns a new GetBigBookOperation from a given name. // The name must be that of a previously created GetBigBookOperation, possibly from a different process. func (c *Client) GetBigBookOperation(name string) *GetBigBookOperation { return &GetBigBookOperation{ - lro: longrunning.InternalNewOperation(c.Connection(), &longrunningpb.Operation{Name: name}), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}), } } // Wait blocks until the long-running operation is completed, returning the response and any errors encountered. // // See documentation of Poll for error-handling information. -func (op *GetBigBookOperation) Wait(ctx context.Context) (*librarypb.Book, error) { +func (op *GetBigBookOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*librarypb.Book, error) { var resp librarypb.Book - ctx = insertXGoog(ctx, op.xGoogHeader) - if err := op.lro.Wait(ctx, &resp); err != nil { + if err := op.lro.Wait(ctx, &resp, opts...); err != nil { return nil, err } return &resp, nil @@ -891,10 +895,9 @@ func (op *GetBigBookOperation) Wait(ctx context.Context) (*librarypb.Book, error // If Poll succeeds and the operation has completed successfully, // op.Done will return true, and the response of the operation is returned. // If Poll succeeds and the operation has not completed, the returned response and error are both nil. -func (op *GetBigBookOperation) Poll(ctx context.Context) (*librarypb.Book, error) { +func (op *GetBigBookOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*librarypb.Book, error) { var resp librarypb.Book - ctx = insertXGoog(ctx, op.xGoogHeader) - if err := op.lro.Poll(ctx, &resp); err != nil { + if err := op.lro.Poll(ctx, &resp, opts...); err != nil { return nil, err } if !op.Done() { @@ -933,34 +936,28 @@ func (op *GetBigBookOperation) Name() string { // Clients can use Poll or other methods to check whether the cancellation succeeded or whether the operation // completed despite cancellation. On successful cancellation, the operation is not deleted; // instead, op.Poll returns an error with code Canceled. -func (op *GetBigBookOperation) Cancel(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Cancel(ctx) +func (op *GetBigBookOperation) Cancel(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Cancel(ctx, opts...) } -// GetBigNothingOperation manages a long-running operation with no result. +// GetBigNothingOperation manages a long-running operation from GetBigNothing. type GetBigNothingOperation struct { lro *longrunning.Operation - - // The metadata to be sent with each request. - xGoogHeader []string } // GetBigNothingOperation returns a new GetBigNothingOperation from a given name. // The name must be that of a previously created GetBigNothingOperation, possibly from a different process. func (c *Client) GetBigNothingOperation(name string) *GetBigNothingOperation { return &GetBigNothingOperation{ - lro: longrunning.InternalNewOperation(c.Connection(), &longrunningpb.Operation{Name: name}), - xGoogHeader: c.xGoogHeader, + lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}), } } // Wait blocks until the long-running operation is completed, returning any error encountered. // // See documentation of Poll for error-handling information. -func (op *GetBigNothingOperation) Wait(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Wait(ctx, nil) +func (op *GetBigNothingOperation) Wait(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Wait(ctx, nil, opts...) } // Poll fetches the latest state of the long-running operation. @@ -970,9 +967,8 @@ func (op *GetBigNothingOperation) Wait(ctx context.Context) error { // If Poll fails, the error is returned and op is unmodified. If Poll succeeds and // the operation has completed with failure, the error is returned and op.Done will return true. // If Poll succeeds and the operation has completed successfully, op.Done will return true. -func (op *GetBigNothingOperation) Poll(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Poll(ctx, nil) +func (op *GetBigNothingOperation) Poll(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Poll(ctx, nil, opts...) } // Metadata returns metadata associated with the long-running operation. @@ -1004,7 +1000,6 @@ func (op *GetBigNothingOperation) Name() string { // Delete deletes a long-running operation. // This method indicates that the client is no longer interested in the operation result. // It does not cancel the operation. -func (op *GetBigNothingOperation) Delete(ctx context.Context) error { - ctx = insertXGoog(ctx, op.xGoogHeader) - return op.lro.Delete(ctx) +func (op *GetBigNothingOperation) Delete(ctx context.Context, opts ...gax.CallOption) error { + return op.lro.Delete(ctx, opts...) }