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

Inversed transport layer for Client #79

Closed
dahlia opened this Issue Jun 20, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@dahlia
Member

dahlia commented Jun 20, 2017

Nirum compiler currently generates client classes of services by inheriting a service and Client at a time. Although the current design helps to generate less duplicated code and works well in ordinary cases, it's not good at adding or changing transport.

Suppose we have 2 services: customer-service and message-service. The current compiler generates 4 classes (2 interfaces and 2 client implementations) from the schema: CustomerService, CustomerServiceClient, MessageService, and MessageServiceClient. These two client classes assume we use the default HTTP transport. What if we need to use our own transport layer (say it's our own authentication protocol based on HTTPS) with these service clients?

One possible way is to subclass these client classes and override hooks like make_request(). Add a class named CustomerServiceClient2 and make it to inherit CustomerServiceClient with overridden make_request(). Also add MessageServiceClient2 and do the same thing. What if we need to add a more service? Add AnotherServiveClient2 and do the same thing. Repeat this when you add a new service.

It's basically because we use inheritance to extend transport. It can be more flexible if we refactor it to use composition instead of inheritance.

The following is how the currently generated code looks like:

class CustomerServiceClient(Client, CustomerService):
    ...

It should be changed to the following way:

class CustomerServiceClient(CustomerService):
    def __init__(self, transport: Transport) -> None:
        ...

In the above Transport is an interface type and we need to provide the built-in transport implementation like HttpTransport. When we use clients the code would look like the below:

client = CustomerServiceClient(transport=HttpTransport('https://api.example.com/'))

@admire93 Any opinions?

@dahlia dahlia added the enhancement label Jun 20, 2017

@kanghyojun

This comment has been minimized.

Member

kanghyojun commented Jun 21, 2017

Sound great! this design make it easy to support various transport like MQ as well. i'm trying to work this issue on this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment