1

I have a nameko service that deals with lots of entities, and having the entrypoints in a single service.py module would render the module highly unreadable and harder to maintain.

So I've decided to split up the module in to multiple Services which are then used to extend the main service. I am kind of worried about dependency injection and thought a dependency like the db, might have multiple instances due to this approach. This is what I have so far:

the customer service module with all customer-related endpoints

# app/customer/service.py

class HTTPCustomerService:
    """HTTP endpoints for customer module"""

    name = "http_customer_service"
    db = None
    context = None
    dispatch = None

    @http("GET,POST", "/customers")
    def customer_listing(self, request):
        session = self.db.get_session()
        return CustomerListController.as_view(session, request)

    @http("GET,PUT,DELETE", "/customers/<uuid:pk>")
    def customer_detail(self, request, pk):
        session = self.db.get_session()
        return CustomerDetailController.as_view(session, request, pk)

and main service module that inherits from customer service, and possibly other abstract services

# app/service.py

class HTTPSalesService(HTTPCustomerService):
    """Nameko http service."""

    name = "http_sales_service"
    db = Database(Base)
    context = ContextData()
    dispatch = EventDispatcher()

and finally I run it with:

nameko run app.service

So this works well, but is the approach right? Especially with regards to dependency injection?

Rodgers Ouma
  • 103
  • 2
  • 13

1 Answers1

1

Yep, this approach works well.

Nameko doesn't introspect the service class until run-time, so it sees whatever standard Python class inheritance produces.

One thing to note is that your base class is not "abstract" -- if you point nameko run at app/customer/service.py it will attempt to run it. Related, if you put your "concrete" subclass in the same module, nameko run will try to run both of them. You can mitigate this by specifying the service class, i.e. nameko run app.services:HTTPSalesService

Matt
  • 2,153
  • 1
  • 18
  • 29
  • any idea why nameko seems to run `HTTPCustomerService` in the above case instead of `HttpSalesService` ? – Rodgers Ouma May 20 '19 at 12:48
  • 1
    Yes. Actually I was incorrect in my statement above -- you don't have to put both classes in the same module to experience this problem. The service inspection also considers classes you've imported, so the base class is included. Mitigation is the same: specify the name of the service class when you call the runner. – Matt May 20 '19 at 16:29