Creating New Services

New services are fairly easy to create. They have to at a bare minimum implement mv3d.util.iservice.IService. Implementing that interface will result in a service that can be specified in the config. Here's an example basic service:

# saved as mv3d.server.hello.py

from twisted.application.service import Service

from mv3d.util.iservice import IService

class HelloService(Service):
    implements(IService)

    greeting = "Hello Service!"
    name = None

    def configure(self, name, cfile):
        self.greeting = cfile.get(name, "greeting")
        self.name = name

    def getInterface(self, client, protocol):
        pass

    def getName(self):
        return self.name

    def isLocal(self):
        return True

We could add this service to a server by editing its config file:

[Server]
serviceName=Hello

[Hello]
type=mv3d.server.hello.HelloService
greeting=Hello MV3D Service!

Once the server starts up, it would be possible to get the new service with the following code:

service = conductor.getNamedService("Hello")

Of course, this service doesn't really do anything interesting. We could add a new function to the service:

    def greet(self, who):
        return "%s, %s" % (who, self.greeting)

It's usually a good idea to create an interface if you are creating a new service.

class IHelloService(IService):
    pass


class HelloService(object):
    implements(IHelloService)

Once you've done that, you can get the service by its interface instead of needing to know its name. This is particularly useful because service names can be anything the user wants.

service = conductor.getLocalService(IHelloService)

Now, at this point, the service can't be accessed from other servers. In order to allow it to be used over the network, you'll have to define some interfaces. This can be done by creating an interface class and returning it when requested from getInterface.

from twisted.spread.pb import Viewable
class HelloView(Viewable):
    def view_greet(self, client, who):
        return self.parent.greet(who)

class HelloService(object):
    ...
    def getInterface(self, client, protocol):
        if protocol == "pb":
            return HelloView(self)

On a client or remote server, we could easily call the greet method remotely.

from twisted.internet.defer import inlineCallbacks

@inlineCallbacks
def getGreeting
    remoteService = yield conductor.getService("pb://hostname:1999/Hello")
    greeting = yield remoteService.greet("Fred")
    print greeting