Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

balancer: Enforce embedding the SubConn interface in implementations #7758

Merged
merged 3 commits into from
Nov 5, 2024

Conversation

arjan-bal
Copy link
Contributor

@arjan-bal arjan-bal commented Oct 18, 2024

Presently, the doc comment on the balancer.SubConn interface mentions that external implementers should embed the balancer.SubConn interface, however, this is not enforced at compilation time:

// This interface is to be implemented by gRPC. Users should not need their own
// implementation of this interface. For situations like testing, any
// implementations should embed this interface. This allows gRPC to add new
// methods to this interface.

This PR adds an unexported method on the interface to add a compile time check for enforcing the requirement.

Release notes transferred to new PR that reworks this slightly.

RELEASE NOTES: None

@arjan-bal arjan-bal added the Type: Internal Cleanup Refactors, etc label Oct 18, 2024
@arjan-bal arjan-bal added this to the 1.69 Release milestone Oct 18, 2024
@arjan-bal arjan-bal requested review from easwars and dfawley October 18, 2024 10:44
@arjan-bal arjan-bal changed the title balancer: Enforce embedding the SubConn interface balancer: Enforce embedding the SubConn interface in implementations Oct 18, 2024
Copy link

codecov bot commented Oct 18, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.81%. Comparing base (d66fc3a) to head (152cbce).
Report is 8 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #7758      +/-   ##
==========================================
+ Coverage   81.71%   81.81%   +0.09%     
==========================================
  Files         374      371       -3     
  Lines       38166    37700     -466     
==========================================
- Hits        31188    30844     -344     
+ Misses       5699     5563     -136     
- Partials     1279     1293      +14     
Files with missing lines Coverage Δ
balancer/balancer.go 96.77% <ø> (ø)
balancer_wrapper.go 84.03% <ø> (ø)
internal/testutils/balancer.go 84.32% <ø> (ø)

... and 33 files with indirect coverage changes

Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a potential breaking change. I suspect it would only break tests (doing mocking?), but it's possible to break actual users. That's OK, we just need to be careful to document the change and also take care when importing the code internally.

@@ -155,6 +155,9 @@ type SubConn interface {
// indicate the shutdown operation. This may be delivered before
// in-progress RPCs are complete and the actual connection is closed.
Shutdown()
// enforceEmbedding is an unexported method to enforce implementers embed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...to force implementers to embed..." or "to enforce that implementers embed".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar fixed.

@dfawley dfawley assigned arjan-bal and unassigned dfawley Oct 18, 2024
@arjan-bal
Copy link
Contributor Author

arjan-bal commented Oct 21, 2024

This is a potential breaking change. I suspect it would only break tests (doing mocking?), but it's possible to break actual users. That's OK, we just need to be careful to document the change and also take care when importing the code internally.

@dfawley , I checked the internal usages and found that adding a private method will break code generated using GoMock, e.g: https://github.com/GoogleCloudPlatform/grpc-gcp-go/blob/d2bc599b72aeef2d85143b234ca7d602ae7f4302/grpcgcp/mocks/mock_balancer.go#L116-L119

Due to the private method, the generated mock no longer implements the balancer.SubConn interface, even though the mock has a private method with the same signature.

Users could manually edit the generated mocks to embed balancer.SubConn. Do you think it's okay to expect users manually edit their mocks?

@arjan-bal arjan-bal assigned dfawley and unassigned arjan-bal Oct 21, 2024
@easwars
Copy link
Contributor

easwars commented Oct 21, 2024

I checked the internal usages and found that adding a private method will break code generated using GoMock

Hmm.. at least internally, mocking is not recommended for Go. I'm not sure about the external world though. Do you have any experience using mocking frameworks and know what is more commonly used and whether they generate code differently wherein the generated code embeds the mocked interface? (some google searching didn't yield anything useful)

Users could manually edit the generated mocks to embed balancer.SubConn. Do you think it's okay to expect users manually edit their mocks?

I guess this is no worse if you didn't use mocking and didn't embed, but chose to implement the methods to satisfy the interface.

@@ -32,6 +32,7 @@ import (

// TestSubConn implements the SubConn interface, to be used in tests.
type TestSubConn struct {
balancer.SubConn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny that we ourselves didn't embed the interface in our tests.

@dfawley
Copy link
Member

dfawley commented Oct 21, 2024

Do you think it's okay to expect users manually edit their mocks?

Probably not if they're generated, unless they're also checked in, and then...maybe. How many instances of this exist? Is it feasible to fix all the ones that we're (indirectly) responsible for?

Copy link
Member

@dfawley dfawley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but we need to wait to check this in until all the internal dependencies are resolved.

@dfawley dfawley removed their assignment Oct 25, 2024
@arjan-bal
Copy link
Contributor Author

The PR in grpc-gcp-go is merged: GoogleCloudPlatform/grpc-gcp-go#89
grpc-gcp-go may need to do a release before we're clear to merge this PR.

@arjan-bal arjan-bal merged commit 43ee172 into grpc:master Nov 5, 2024
15 checks passed
@arjan-bal arjan-bal deleted the subconn-enforce-embedding branch November 5, 2024 17:52
@arjan-bal arjan-bal added the Area: Resolvers/Balancers Includes LB policy & NR APIs, resolver/balancer/picker wrappers, LB policy impls and utilities. label Nov 6, 2024
misvivek pushed a commit to misvivek/grpc-go that referenced this pull request Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Resolvers/Balancers Includes LB policy & NR APIs, resolver/balancer/picker wrappers, LB policy impls and utilities. Type: Internal Cleanup Refactors, etc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants