Skip to content

Commit

Permalink
THRIFT-5233: Handle I/O timeouts in go library
Browse files Browse the repository at this point in the history
Client: go

As discussed in the JIRA ticket, this commit changes how we handle I/O
timeouts in the go library.

This is a breaking change that adds context to all Read*, Write*, and
Skip functions to TProtocol, along with the compiler change to support
that, and also adds context to TStandardClient.Recv, TDeserializer,
TStruct, and a few others.

Along with the function signature changes, this commit also implements
context cancellation check in the following TProtocol's ReadMessageBegin
implementations:

- TBinaryProtocol
- TCompactProtocol
- THeaderProtocol

In those ReadMessageBegin implementations, if the passed in context
object has a deadline attached, it will keep retrying the I/O timeout
errors, until the deadline on the context object passed. They won't
retry I/O timeout errors if the passed in context does not have a
deadline attached (still return on the first error).
  • Loading branch information
fishy committed Jun 15, 2020
1 parent 3f78c70 commit 4dca38e
Show file tree
Hide file tree
Showing 24 changed files with 982 additions and 902 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [THRIFT-5138](https://issues.apache.org/jira/browse/THRIFT-5138) - Swift generator does not escape keywords properly
- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - In Go library TProcessor interface now includes ProcessorMap and AddToProcessorMap functions.
- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - cpp: use all getaddrinfo() results when retrying failed bind() in T{Nonblocking,}ServerSocket
- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - go: Now all Read*, Write* and Skip functions in TProtocol accept context arg

### Java

Expand All @@ -24,6 +25,7 @@
- [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer.
- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ClientMiddleware function type and WrapClient function to support wrapping a TClient with middleware functions.
- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions.
- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - Add context deadline check to ReadMessageBegin in TBinaryProtocol, TCompactProtocol, and THeaderProtocol.

## 0.13.0

Expand Down
140 changes: 70 additions & 70 deletions compiler/cpp/src/thrift/generate/t_go_generator.cc

Large diffs are not rendered by default.

48 changes: 26 additions & 22 deletions lib/go/thrift/application_exception.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

package thrift

import (
"context"
)

const (
UNKNOWN_APPLICATION_EXCEPTION = 0
UNKNOWN_METHOD = 1
Expand Down Expand Up @@ -51,8 +55,8 @@ var defaultApplicationExceptionMessage = map[int32]string{
type TApplicationException interface {
TException
TypeId() int32
Read(iprot TProtocol) error
Write(oprot TProtocol) error
Read(ctx context.Context, iprot TProtocol) error
Write(ctx context.Context, oprot TProtocol) error
}

type tApplicationException struct {
Expand All @@ -75,9 +79,9 @@ func (p *tApplicationException) TypeId() int32 {
return p.type_
}

func (p *tApplicationException) Read(iprot TProtocol) error {
func (p *tApplicationException) Read(ctx context.Context, iprot TProtocol) error {
// TODO: this should really be generated by the compiler
_, err := iprot.ReadStructBegin()
_, err := iprot.ReadStructBegin(ctx)
if err != nil {
return err
}
Expand All @@ -86,7 +90,7 @@ func (p *tApplicationException) Read(iprot TProtocol) error {
type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)

for {
_, ttype, id, err := iprot.ReadFieldBegin()
_, ttype, id, err := iprot.ReadFieldBegin(ctx)
if err != nil {
return err
}
Expand All @@ -96,34 +100,34 @@ func (p *tApplicationException) Read(iprot TProtocol) error {
switch id {
case 1:
if ttype == STRING {
if message, err = iprot.ReadString(); err != nil {
if message, err = iprot.ReadString(ctx); err != nil {
return err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return err
}
}
case 2:
if ttype == I32 {
if type_, err = iprot.ReadI32(); err != nil {
if type_, err = iprot.ReadI32(ctx); err != nil {
return err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return err
}
}
default:
if err = SkipDefaultDepth(iprot, ttype); err != nil {
if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
return err
}
}
if err = iprot.ReadFieldEnd(); err != nil {
if err = iprot.ReadFieldEnd(ctx); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
if err := iprot.ReadStructEnd(ctx); err != nil {
return err
}

Expand All @@ -133,38 +137,38 @@ func (p *tApplicationException) Read(iprot TProtocol) error {
return nil
}

func (p *tApplicationException) Write(oprot TProtocol) (err error) {
err = oprot.WriteStructBegin("TApplicationException")
func (p *tApplicationException) Write(ctx context.Context, oprot TProtocol) (err error) {
err = oprot.WriteStructBegin(ctx, "TApplicationException")
if len(p.Error()) > 0 {
err = oprot.WriteFieldBegin("message", STRING, 1)
err = oprot.WriteFieldBegin(ctx, "message", STRING, 1)
if err != nil {
return
}
err = oprot.WriteString(p.Error())
err = oprot.WriteString(ctx, p.Error())
if err != nil {
return
}
err = oprot.WriteFieldEnd()
err = oprot.WriteFieldEnd(ctx)
if err != nil {
return
}
}
err = oprot.WriteFieldBegin("type", I32, 2)
err = oprot.WriteFieldBegin(ctx, "type", I32, 2)
if err != nil {
return
}
err = oprot.WriteI32(p.type_)
err = oprot.WriteI32(ctx, p.type_)
if err != nil {
return
}
err = oprot.WriteFieldEnd()
err = oprot.WriteFieldEnd(ctx)
if err != nil {
return
}
err = oprot.WriteFieldStop()
err = oprot.WriteFieldStop(ctx)
if err != nil {
return
}
err = oprot.WriteStructEnd()
err = oprot.WriteStructEnd(ctx)
return
}
Loading

0 comments on commit 4dca38e

Please sign in to comment.