Skip to content

Commit

Permalink
Change client to return instances of our classes.
Browse files Browse the repository at this point in the history
This changes the client code generated for `--target thrift-server` so that it returns instances of the generated thrift classes instead of plain objects. I believe the client code generated for `--target apache` already behaves this way.

One advantage is this allows `instanceof` to be used on Thrift responses, which makes exceptions [distinguishable from each other](creditkarma#181) using `instanceof`. It would also increase the usefulness of having [exception classes derive from Error](creditkarma#178).

The change itself is small and easy. The compiler already generates "MyEndpoint__Result" classes that have a read() function that instantiates the class, I just needed to call it from the appropriate place in the Client class.

To review this change it'll be helpful if you're familiar with the various classes that are generated. I'll refrain from trying to describe it here--you're better off looking some generated code on your own. Here's a diff showing how this change affects a generated ping function. This is in the Client class:
```
     public ping(context?: Context): Promise<string> {
         const writer: thrift.TTransport = new this.transport();
         const output: thrift.TProtocol = new this.protocol(writer);
         output.writeMessageBegin("ping", thrift.MessageType.CALL, this.incrementRequestId());
         const args: IPing__ArgsArgs = {};
         Ping__ArgsCodec.encode(args, output);
         output.writeMessageEnd();
         return this.connection.send(writer.flush(), context).then((data: Buffer) => {
             const reader: thrift.TTransport = this.transport.receiver(data);
             const input: thrift.TProtocol = new this.protocol(reader);
             try {
                 const { fieldName: fieldName, messageType: messageType }: thrift.IThriftMessage = input.readMessageBegin();
                 if (fieldName === "ping") {
                     if (messageType === thrift.MessageType.EXCEPTION) {
                         const err: thrift.TApplicationException = thrift.TApplicationExceptionCodec.decode(input);
                         input.readMessageEnd();
                         return Promise.reject(err);
                     }
                     else {
-                        const result: IPing__Result = Ping__ResultCodec.decode(input);
+                        const result: Ping__Result = Ping__Result.read(input);
                         input.readMessageEnd();
                         if (result.success != null) {
                             return Promise.resolve(result.success);
                         }
                         else {
                             return Promise.reject(new thrift.TApplicationException(thrift.TApplicationExceptionType.UNKNOWN, "ping failed: unknown result"));
                         }
                     }
                 }
                 else {
                     return Promise.reject(new thrift.TApplicationException(thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function: " + fieldName));
                 }
             }
             catch (err) {
                 return Promise.reject(err);
             }
         });
     }
```

You'll notice that I also changed the type of `result` from `IPing__Result` to `Ping__Result`. This isn't important and could be reverted, but I think it's better this way. I like keeping types specific until the point where it's useful for them to be generic. I'd advocate for making the same change to the types of struct class members (would need to change these types, I think: https://github.com/creditkarma/thrift-typescript/blob/e8931ff0d98c871360af99bbfa805cfd088d2f0e/src/main/render/thrift-server/struct/class.ts#L293 and https://github.com/creditkarma/thrift-typescript/blob/e8931ff0d98c871360af99bbfa805cfd088d2f0e/src/main/render/thrift-server/struct/reader.ts#L51), though that isn't of immediately use to me personally and I don't intend to pursue it.
  • Loading branch information
markdoliner-doma committed Jun 1, 2020
1 parent e8931ff commit 1eba49d
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/main/render/thrift-server/service/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import {
import { Resolver } from '../../../resolver'
import { createBufferType, createPromiseType } from '../../shared/types'
import { createClassConstructor } from '../../shared/utils'
import { looseName, strictName, toolkitName } from '../struct/utils'
import { className, looseName, toolkitName } from '../struct/utils'

function extendsAbstract(): ts.HeritageClause {
return ts.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [
Expand Down Expand Up @@ -515,7 +515,7 @@ function createConnectionSend(): ts.CallExpression {
)
}

// const result: GetUserResult = GetUserResultCodec.decode(input);
// const result: GetUser__Result = GetUser__Result.read(input);
function createNewResultInstance(
def: FunctionDefinition,
state: IRenderState,
Expand All @@ -525,16 +525,16 @@ function createNewResultInstance(
COMMON_IDENTIFIERS.result,
ts.createTypeReferenceNode(
ts.createIdentifier(
strictName(createStructResultName(def), def.type, state),
className(createStructResultName(def), state),
),
undefined,
),
ts.createCall(
ts.createPropertyAccess(
ts.createIdentifier(
toolkitName(createStructResultName(def), state),
className(createStructResultName(def), state),
),
COMMON_IDENTIFIERS.decode,
COMMON_IDENTIFIERS.read,
),
undefined,
[COMMON_IDENTIFIERS.input],
Expand Down

0 comments on commit 1eba49d

Please sign in to comment.