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

Design and consider porting from hydrus #1

Open
Mec-iS opened this issue Feb 21, 2018 · 6 comments
Open

Design and consider porting from hydrus #1

Mec-iS opened this issue Feb 21, 2018 · 6 comments

Comments

@Mec-iS
Copy link
Contributor

Mec-iS commented Feb 21, 2018

In Falcon every endpoint is a Resource that inherits form Api, all the endpoints and methods have to be created dynamically by parsing the HYDRA ApiDoc as happens in hydrus. A lot of code can be ported to Falcon on_* methods, trying to preserve hydrus functional style.

The Application should contain a design document and detail how the student wants to make the porting possible.

@vddesai1871
Copy link
Collaborator

vddesai1871 commented Feb 26, 2018

Hey, @Mec-iS @xadahiya @chrizandr I have started working on it but I have a couple of questions.

1> How should we replace the application context code of Flask that we have in utils.py and have set_session, set_server_name etc methods? Right now I am using Falcon middleware to replace it.

Using Falcon middleware in replacement of Flask app context is the right thing to do? I do not know any other options.

The following gist shows the code. Right now it only works for the entry point.

https://gist.github.com/vddesai1998/2037ea34f76d2103616447e8034da673

2> Right now we are creating the scoped session in main.py and using it everywhere.Instead, we should instantiate a session at the start of the request and remove it when the request ends.
We might do it with the help of Falcon middleware.

class SessionManager:
    def __init__(self, session):
        self.session = session

    def process_resource(self, req, resp, resource, params):
        resource.session = self.session()

    def process_response(self, req, resp, resource, req_succeeded):
        if hasattr(resource, 'session'):
            session.remove()

@Mec-iS
Copy link
Contributor Author

Mec-iS commented Feb 26, 2018

@vddesai1998
Yeah Flask is a functional framework so everything is implemented using nested contexts and other Functional mechanics (based on the concept of "closure"). Falcon leverages instead more sequential approach but the request context can still be "encapsulated" to make it safer or make functions reusable. About the session manager, the best way is to create a connection at Api (class) level and manage the session as showed here and in your example.
Falcon works with middleware paradigm, for an extensive example see here.
Run more experiments and write a good proposal about.

@vddesai1871
Copy link
Collaborator

vddesai1871 commented Feb 27, 2018

@Mec-iS To encapsulate request context I tried few things and settled with these solutions.Both are working.
1>I created a base class which has these functions as methods and all the Resource classes of Falcon inherit from this class.

class ResourceBase(object):
    def doc(self, resp):
        try:
            apidoc = resp.context['api_doc']
        except KeyError:
            apidoc = resp.context['api_doc'] = doc_writer_sample.api_doc
        return apidoc

    def get_authentication(self, resp) -> bool:
        """Check wether API needs to be authenticated or not."""
        try:
            authentication = resp.context['authentication']
        except KeyError:
            authentication = resp.context['authentication'] = False
        return authentication

    def get_api_name(self, resp) -> str:
        """Get the server API name."""
        try:
            api_name = resp.context['api_name']
        except KeyError:
            api_name = resp.context['api_name'] = "api"
        return api_name

    def get_hydrus_server_url(self, resp) -> str:
        """Get the server URL."""
        try:
            hydrus_server_url = resp.context['hydrus_server_url']
        except KeyError:
            hydrus_server_url = resp.context['hydrus_server_url'] = "http://localhost/"

        return hydrus_server_url

    def get_session(self, resp) -> Session:
        """Get the Database Session for the server."""
        try:
            session = resp.context['db_session']
        except KeyError:
            session = scoped_session(sessionmaker(bind=engine))
            session = resp.context['db_session'] = session()
        return session

class Index(ResourceBase):
    """Class for the EntryPoint."""

    def on_get(self, req, resp)-> falcon.Response:
        """Return main entrypoint for the api."""
        resp.body = json.dumps(self.doc(resp).entrypoint.get())
        resp = set_response_headers(resp)


Also as you can see I have replaced getattr() function calls with try - except block as mentioned here
2>
All the resources classes are not going to use every method and some functions outside the classes also require this getter methods so
I think we should define this getter methods in utils.py and use them where we need them instead of this base class approach.
What do you think?
Now my code is working for GET requests on Item.
Should I start working on other projects I am interested in or keep working on this?

@Mec-iS
Copy link
Contributor Author

Mec-iS commented Feb 27, 2018

resp.body = json.dumps(self.doc(resp).entrypoint.get())

try to use resp.media with JSON serialization, it makes the serialization much faster

The challenge is to create the classes starting from an Hydra ApiDoc document.

You can work on whatever you want, consider writing a proposal that includes this task, beside other related ones as defined in https://hydra-gsoc.appspot.com/#ideas

@vddesai1871
Copy link
Collaborator

vddesai1871 commented Feb 27, 2018

The challenge is to create the classes starting from an Hydra ApiDoc document.

Can you elaborate please?

@Mec-iS
Copy link
Contributor Author

Mec-iS commented Feb 27, 2018

Hydrus reads from the HYDRA ApiDocumentation file written in JSON-LD to set up and deploy the server so that the server publishes the endpoints specified in the ApiDoc. In the same way the Falcon version should parse the ApiDoc (you can reuse the functions written for Flask) to create Falcon API classes.

vddesai1871 pushed a commit that referenced this issue Jun 10, 2018
vddesai1871 pushed a commit that referenced this issue Jun 10, 2018
Switching to develop for now
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

No branches or pull requests

2 participants