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

[Feature Request] Get a registered dependency outside of route handlers as well #201

Open
guacs opened this issue Jun 5, 2023 · 3 comments

Comments

@guacs
Copy link

guacs commented Jun 5, 2023

Is your feature request related to a problem? Please describe your use case.
I am trying to access a service that I have registered as a dependency in an event handler to a custom signal.

class MyService:
    
    def __init__(self, connection: DBConnection):
        self._connection = connection

@app.signal("some.dummy.event")
def dummy_event_handler(**context):
    app = Sanic.get_app("my-app")
    request = Request.get_current()
   
    dependency_callable = app.ext._injection_registry.get(dependency_type)
    # I'm not sure what the impact of using this request object is.
    # What if I'm calling this after the request that dispatched this event
    # has already been processed and the response was sent?
    service = await dependency_callable(request)
    ...

Describe the solution you'd like
It would be nice to get an API which takes in a type and attempts to get the dependency from the registry.

class MyService:
    ...

@app.signal("some.dummy.event")
def dummy_event_handler(**context):
    service = Sanic.get_app("my-app").ext.get_dependency(MyService)
    # do something with the service
@BDadmehr0
Copy link

BDadmehr0 commented Jun 5, 2023

Certainly! Here's an example of an API that takes a type and attempts to retrieve the corresponding dependency from the registry:

class DependencyRegistry:
    def __init__(self):
        self._registry = {}

    def register_dependency(self, dependency_type, dependency):
        self._registry[dependency_type] = dependency

    def get_dependency(self, dependency_type):
        return self._registry.get(dependency_type)


class MyService:
    def __init__(self, connection: DBConnection):
        self._connection = connection


app = Sanic("my-app")
registry = DependencyRegistry()


@app.route("/dependency/<dependency_type>")
async def get_dependency(request, dependency_type):
    dependency = registry.get_dependency(dependency_type)
    if dependency is None:
        return json({"error": "Dependency not found"}, status=404)
    return json({"dependency": str(dependency)})


@app.listener("before_server_start")
async def setup_registry(app, loop):
    # Register dependencies in the registry
    registry.register_dependency(DBConnection, "database_connection")


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

In this example, we have a DependencyRegistry class that maintains a dictionary _registry for storing dependencies. It provides methods to register and retrieve dependencies.

The MyService class is just a placeholder representing a class that requires dependencies.

The Sanic app (app) is created with the name "my-app". We define a route /dependency/<dependency_type> that accepts a dependency_type parameter. When a GET request is made to this route, the API attempts to retrieve the corresponding dependency from the registry based on the provided dependency_type. If the dependency is found, it is returned in the response. Otherwise, a 404 error response is returned.

In the before_server_start listener, we can register dependencies in the registry. In this example, we register a DBConnection dependency with the value "database_connection".

You can modify and expand this example to suit your specific needs.

@guacs
Copy link
Author

guacs commented Jun 5, 2023

I'm sorry @BDadmehr0 , but I don't think your proposed solution is what I'm looking for. When I said API, I wasn't talking about an HTTP endpoint but in the more general sense. Also your DependencyRegistry doesn't handle resolving the dependencies required by the dependency I'm trying to get.

@BDadmehr0
Copy link

Sorry, but I can't think of any other solution

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