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

encoding/thrift: Add mechanisms to handle inbound requests via thriftrw's 'nowire' implementation #2084

Merged
merged 23 commits into from
Aug 30, 2021

Conversation

witriew
Copy link
Collaborator

@witriew witriew commented Jul 22, 2021

thriftrw's 'nowire' implementation (known as 'streaming' in the thriftrw
context) is an alternative wire-compatible implementation of the Thrift
protocol that bypasses the intermediate 'thriftrw.Wire' representation and
'streams' the protocol directly to the related objects.

This provides the mechanisms to handle 'Call's made via the 'nowire'
implementation instead of the existing 'Wire'-intermediary format. Doing so
involved creating a new type, thriftNoWireHandler, that implements both a
transport.UnaryHandler and a transport.OnewayHandler.

These call into a new interface, NoWireHandler (which will be implemented by
generated code, for each procedure), that understands how to unpack the request
using thriftrw's 'nowire' primitives (stream.RequestReadeer), execute the
request, and return objects that understand what's involved in sending back a
response, if it's a Unary call.

encoding/thrift/inbound_nowire.go Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
@witriew witriew changed the title encoding/thrift: Add mechanisms to handle requests via thriftrw's 'nowire' implementaiton encoding/thrift: Add mechanisms to handle requests via thriftrw's 'nowire' implementation Aug 2, 2021
@witriew witriew force-pushed the wit/inbounds_nowire_handler branch 2 times, most recently from e1f115f to e78be5f Compare August 4, 2021 00:59
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Show resolved Hide resolved
@witriew witriew requested review from Dogild and AllenLuUber August 5, 2021 05:39
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
@abhinav
Copy link
Contributor

abhinav commented Aug 11, 2021

Some context on the discussion @witriew and I had about this, which, in
hindsight, I should have written down and shared with you, @Dogild and
@AllenLuUber.

Some of the decisions made in encoding/thrift, after a couple years of
hindsight, were not great. For example, one of these is the decision to use
newtype wrappers around funcs (like type UnaryHandler func(..)). This makes
it impossible to have a clean upgrade path for that implementation. For
example, had we used a singular Handler interface, we'd be able to add the
new NoWireHandler interface and internally upgrade from Handler to
NoWireHandler if available with fewer intrusive changes.

When Wit was designing the interfaces here, I suggested that since these were
new APIs largely unencumbered by the burden of backwards comaptibility, he
should err towards choices that we would make today if we were designing these
APIs from scratch.

encoding/thrift/inbound_nowire.go Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Show resolved Hide resolved
encoding/thrift/inbound_nowire_test.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire_test.go Outdated Show resolved Hide resolved
body stream.Enveloper
}

var _ NoWireHandler = (*responseHandler)(nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any chance to use a mock for NoWireHandler?

Copy link
Contributor

Choose a reason for hiding this comment

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

Addendum to the previous comment: For objects with behavioral, mocks can be preferable if the behavior is non-trivial.

Alternatively, a test-only noWireHandlerFunc type that allows test cases to write the behavior inline as needed is also a good option if the assertions aren't shared between the different cases.

type noWireHandlerFunc func(context.Context, *NoWireCall) (NoWireResponse, error)

func (f noWireHandlerFunc) HandleNoWire(ctx context.Context, nwc *NoWireCall) (NoWireResponse, error) {
  return f(ctx, nwc)
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the case of the NoWireHandler stub, I wanted to ensure that the stuff thats passed into HandleNoWire is what is expected. Since all of the calls here have effectively the same checks, it seems cleaner to have the stub that does all of this at once instead of repeating these checks for each of the mocks.

@Dogild Dogild changed the title encoding/thrift: Add mechanisms to handle requests via thriftrw's 'nowire' implementation encoding/thrift: Add mechanisms to handle inbound requests via thriftrw's 'nowire' implementation Aug 12, 2021
@witriew witriew force-pushed the wit/thriftrw_bump-and-gen branch from 6cadf3a to 13ea32e Compare August 17, 2021 21:30
@witriew witriew force-pushed the wit/inbounds_nowire_handler branch from c9d1ad3 to b26373b Compare August 17, 2021 21:33
@abhinav
Copy link
Contributor

abhinav commented Aug 18, 2021

Okay, so this stack isn't green because of:

# go.uber.org/yarpc/encoding/thrift [go.uber.org/yarpc/encoding/thrift.test]
./inbound_nowire_test.go:248:3: cannot use proto (type *streamtest.MockRequestReader) as type stream.Protocol in field value:
        *streamtest.MockRequestReader does not implement stream.Protocol (missing Reader method)

That's a result of thriftrw/thriftrw-go#532 — RequestReaders and Protocols are different interfaces now so the same object cannot be used for them.

Given that this is a new code path, I don't see value in doing upgrade-protocol-to-requestreader dance and just having it be RequestReader-only: All stream based implementations must implement RequestReader. Going to update the PR stack with fixes.

@abhinav abhinav force-pushed the wit/inbounds_nowire_handler branch from 41afa2e to 2aa54c0 Compare August 18, 2021 22:00
@codecov
Copy link

codecov bot commented Aug 18, 2021

Codecov Report

Merging #2084 (68ba5cd) into nowiredev (e76e1ed) will increase coverage by 0.03%.
The diff coverage is 91.48%.

Impacted file tree graph

@@              Coverage Diff              @@
##           nowiredev    #2084      +/-   ##
=============================================
+ Coverage      87.58%   87.61%   +0.03%     
=============================================
  Files            247      248       +1     
  Lines          13731    13772      +41     
=============================================
+ Hits           12026    12067      +41     
  Misses          1325     1325              
  Partials         380      380              
Impacted Files Coverage Δ
encoding/thrift/thriftrw-plugin-yarpc/server.go 100.00% <ø> (ø)
encoding/thrift/inbound_nowire.go 90.24% <90.24%> (ø)
encoding/thrift/inbound.go 93.02% <100.00%> (ø)
encoding/thrift/outbound.go 84.61% <100.00%> (ø)
encoding/thrift/register.go 83.78% <100.00%> (ø)
serialize/serialize.go 76.47% <100.00%> (ø)
peer/hashring32/internal/hashring32/hashring32.go 97.29% <0.00%> (+1.08%) ⬆️
transport/http/peer.go 97.14% <0.00%> (+1.90%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e76e1ed...68ba5cd. Read the comment docs.

@witriew witriew requested review from Dogild and abhinav August 19, 2021 23:36
Copy link
Contributor

@abhinav abhinav left a comment

Choose a reason for hiding this comment

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

LGTM besides nits.

encoding/thrift/inbound_nowire_test.go Outdated Show resolved Hide resolved
body stream.Enveloper
}

var _ NoWireHandler = (*responseHandler)(nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Addendum to the previous comment: For objects with behavioral, mocks can be preferable if the behavior is non-trivial.

Alternatively, a test-only noWireHandlerFunc type that allows test cases to write the behavior inline as needed is also a good option if the assertions aren't shared between the different cases.

type noWireHandlerFunc func(context.Context, *NoWireCall) (NoWireResponse, error)

func (f noWireHandlerFunc) HandleNoWire(ctx context.Context, nwc *NoWireCall) (NoWireResponse, error) {
  return f(ctx, nwc)
}

encoding/thrift/thriftrw-plugin-yarpc/server.go Outdated Show resolved Hide resolved
encoding/thrift/thriftrw-plugin-yarpc/server.go Outdated Show resolved Hide resolved
encoding/thrift/thriftrw-plugin-yarpc/server.go Outdated Show resolved Hide resolved
encoding/thrift/inbound_nowire.go Outdated Show resolved Hide resolved
@witriew witriew force-pushed the wit/thriftrw_bump-and-gen branch from 3bc1991 to 947a4c0 Compare August 25, 2021 06:29
@witriew witriew force-pushed the wit/inbounds_nowire_handler branch from c390896 to 2b1cadd Compare August 25, 2021 06:34
@witriew witriew force-pushed the wit/thriftrw_bump-and-gen branch from 947a4c0 to 97c57f6 Compare August 27, 2021 20:44
@witriew witriew force-pushed the wit/inbounds_nowire_handler branch from 2b1cadd to 138ede4 Compare August 27, 2021 20:50
@witriew witriew force-pushed the wit/thriftrw_bump-and-gen branch from 97c57f6 to 86a7fb7 Compare August 30, 2021 19:25
…nal/crossdock, and internal/examples

Bump thriftrw-go to consume the new no-wire (streaming) implementation.  Also
stop using deprecated fields (except in tests) and regenerate all of the
thriftrw relevant files.
@witriew witriew force-pushed the wit/thriftrw_bump-and-gen branch 2 times, most recently from 4415d06 to 99eb629 Compare August 30, 2021 19:34
witriew and others added 21 commits August 30, 2021 12:35
…wire' implementaiton

thriftrw's 'nowire' implementation (known as 'streaming' in the thriftrw
context) is an alternative wire-compatible implementation of the Thrift
protocol that bypasses the intermediate 'thriftrw.Wire' representation and
'streams' the protocol directly to the related objects.

This provides the mechanisms to handle 'Call's made via the 'nowire'
implementation instead of the existing 'Wire'-intermediary format.  Doing so
involved creating a new type, `thriftNoWireHandler`, that implements both a
`transport.UnaryHandler` and a `transport.OnewayHandler`.

These call into a new interface, `NoWireHandler` (which will be implemented by
generated code, for each procedure), that understands how to unpack the request
using thriftrw's 'nowire' primitives (`stream.RequestReadeer`), execute the
request, and return objects that understand what's involved in sending back a
response, if it's a Unary call.
Since this is a completely green path, we don't need to make
stream.RequestReader an optional upgrade.
Co-authored-by: Abhinav Gupta <abg@uber.com>
Co-authored-by: Abhinav Gupta <abg@uber.com>
@witriew witriew force-pushed the wit/inbounds_nowire_handler branch from 138ede4 to 68ba5cd Compare August 30, 2021 19:36
Base automatically changed from wit/thriftrw_bump-and-gen to nowiredev August 30, 2021 19:41
@witriew witriew merged commit 2e6fb46 into nowiredev Aug 30, 2021
@witriew witriew deleted the wit/inbounds_nowire_handler branch August 30, 2021 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants