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

Setup starter, ci and implemented POC / Unary Call. #8

Merged
merged 1 commit into from
Nov 3, 2017

Conversation

jonathan-casarrubias
Copy link
Contributor

@jonathan-casarrubias jonathan-casarrubias commented Nov 2, 2017

Implemented a vanilla version of the loopback extension
starter, made some tweaks and added travis & appveyor config files.

Added lint fix to pretest
Implemented grpc Decorator
Implemented grpc server provider
Implemented grpc server
Implemented grpc sequence
Implemented grpc bindings
Implemented grpc configs
Implemented unit tests

@jonathan-casarrubias jonathan-casarrubias self-assigned this Nov 2, 2017
@jonathan-casarrubias jonathan-casarrubias force-pushed the jcasarrubias/playground branch 4 times, most recently from 8dd1769 to 9da53f8 Compare November 2, 2017 19:59
@@ -0,0 +1,35 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we name it grpc.decorator.ts?

* }
* }
*/
export function rpc() {
Copy link
Contributor

Choose a reason for hiding this comment

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

grpc?

@@ -0,0 +1,56 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
Copy link
Contributor

Choose a reason for hiding this comment

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

grpc?

@raymondfeng
Copy link
Contributor

@jonathan-casarrubias Great start! I added a few minor comments.

@jonathan-casarrubias
Copy link
Contributor Author

jonathan-casarrubias commented Nov 2, 2017

@raymondfeng thanks for reviewing, also let me elaborate why I'm using rpc.

From gRPC Docs
image

What we are actually implementing with the @rpc decorator are RPC Methods (gRPC stands for the entire RPC System), IMO following semantics would help understand easier to people the reading of the GRPC documentation vs LB4 implementation.

For instance, the entire module is named grpc.component which attempts to achieve the entire gRPC functionality, rpc stands just for RPC methods.

Thoughts?

@raymondfeng
Copy link
Contributor

I see. With more extensions contributing decorators, there are potentially name conflicts. Maybe we should use a namespace such as @grpc.rpc but that might be verbose. I guess @grpc at method level is still fine.

@jonathan-casarrubias
Copy link
Contributor Author

jonathan-casarrubias commented Nov 2, 2017

@raymondfeng I see your point too and for that I have a couple of notes

1.- I see a little odd -but possible- people using 2 RPC systems within LB at the same time. But if that is the case, then:
2.- That usually is fixed at language level:

import {rpc as grpc} from '@loopback/grpc';
import {rpc as orpc} from '@other/orpc';

That way the decorator maintains the original semantic and package conflicts would be fixed at imports.

Maybe I'm being to squared in terms of semantics, but I still think that can be easily fixed using what I describe above, at the end.... They -the developers- would also be able to import another grpc package that would conflict with the decorator and the fix would be the same I describe above.

for instance, importing the grpc module import * as grpc from 'grpc' while also trying to import the decorator import {grpc} from '@loopback/grpc'.

Anyway if you still believe @grpc is better for any reason, then we can just change that and won't hurt that much :P as if we throw the rest of the code away.... lol

Thoughts?

@raymondfeng
Copy link
Contributor

I'm leaning toward @grpc as rpc is too generic. If a developer prefers @rpc, he/she can do the following (as you proposed :-):

import {grpc as rpc} from '@loopback/grpc`;

@jonathan-casarrubias
Copy link
Contributor Author

@raymondfeng ok cool, lets do that then... I'll change to grpc all around.

Cheers!
Jon

@jonathan-casarrubias
Copy link
Contributor Author

@raymondfeng I just did those changes and squached the commit... Now everything related to the decorator is referenced as grpc instead of rpc.

cheers 😄
Jon

@bajtos
Copy link
Member

bajtos commented Nov 3, 2017

@jonathan-casarrubias would you mind moving the project-setup-related changes to a standalone PR, so that we can land it quickly and get those changes out of our way? Quite often, I review pull requests in whole, and it costs me a lot of time and energy to always skip changes that are not important for the feature being implemented.

@bajtos
Copy link
Member

bajtos commented Nov 3, 2017

package-lock.json

IMO, package-lock is pretty harmful when developing modules. When you clone this repo and install dependencies, you get the locked down version of the deps, which is different from the versions that will be installed by our users, when they install this module from npm. What's even worse, our CI will do the same, therefore we will be testing our code against a different set of dependencies that our actual users will use.

The solution: add .npmrc file to disable package-lock functionality and remove package-lock.json file.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

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

Great start!

*/
@grpc()
public sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name});
Copy link
Member

Choose a reason for hiding this comment

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

I have two comments about this example.

  1. How is Greeter#sayHello linked to the correct service/procedure from the proto file?

  2. It's the task of the transport layer to convert the transport-specific request data into typed and validated arguments of a controller method. The controller methods should not need to deal with low-level transport-specific API like call.request.name, this should be handled by the framework.

class MyController implements Greeter {
  sayHello({name}: HelloRequest): HelloResponse {
    return {message: `hello ${name}`};
  }
}

Here are some of the benefits of this approach:

  • The user can focus on writing the business logic in typescript/javascript, possibly in a transport-independent way.
  • Because both request and response are typed (based on the information we already have in the .proto file), the TypeScript compiler can catch many errors at compile time.

it('defines reflection metadata for rpc method', () => {
class Greeter implements GreeterInterface {
@grpc()
SayHello(request: HelloRequest): HelloReply {
Copy link
Member

Choose a reason for hiding this comment

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

Nice! This is what I was looking for in my previous comment. Looks like the implementation is good but the README needs an update?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes the readme is the one outdated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done I updated the docs and addressed the rest of the comments, I'm landing this PR now :)

const flags: {[key: string]: boolean} = {};
const app: Application = givenApplication();
app.controller(Greeter);
const controller = app.find('controllers.Greeter').pop();
Copy link
Member

Choose a reason for hiding this comment

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

Since this code is living in the file called grpc.decorator.unit.ts, it should contain a unit test that's testing the decorator in isolation, stubbing any dependencies as needed. You should not be using the full Application object! Unfortunately, we are behind on docs for extension developers (see loopbackio/loopback-next#579), but some relevant information can be found in these places:

In this particular case, just scan Greeter.prototype directly.

let controllerMethods: string[] = [];
const flags: {[key: string]: boolean} = {};
const proto = Greeter.prototype;
// ...

}
expect(controllerMethods).to.eql(['SayHello', 'Helper']);
expect(flags.SayHello).to.be.true();
expect(flags.Helper).to.be.undefined();
Copy link
Member

Choose a reason for hiding this comment

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

When something goes wrong here, e.g. there is a typo in SayHello, then these two checks won't provide enough information to troubleshoot the problem.

A better approach is to use deepEqual and test the whole object.

expect(flags).to.deepEqual({
  SayHello: true,
  // Helper: ignored
});

describe('GrpcComponent', () => {
// GRPC Component Configurations
it('defines grpc component configurations', async () => {
const app: Application = givenApplication();
Copy link
Member

Choose a reason for hiding this comment

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

Ditto - unit tests should not depend on other objects like Application. I think you should move this file to test/acceptance/grpc.component.acceptance.ts.

@virkt25 you have the most practical experience with testing a component. What's your recommendation - how to test the component itself?

@bajtos bajtos mentioned this pull request Nov 3, 2017
Implemented a vanilla version of the loopback extension
starter, made some tweaks and added travis & appveyor config files.

Added lint fix to pretest
Implemented grpc Decorator
Implemented grpc server provider
Implemented grpc server
Implemented grpc sequence
Implemented grpc bindings
Implemented grpc configs
Implemented unit tests

- Fix: #7
- Fix: #4
- Fix: #3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement GRPC Server Provider Setup Project Scaffold
3 participants